Nginx介绍
Ningx应用场景
Windows环境下安装Nginx
Windows环境下实现反向代理
Windows环境下实现负载均衡
实现网关接口跨域解决方案
实现防盗链
防止DDOS
安装Nginx
实现反向代理
Linux环境下nginx+keepalived实现高可用
Session共享解决方案
什么是集群?
什么是Nginx
nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。由俄罗斯的程序设计师Igor Sysoev所开发,官方测试nginx能够支支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定,所以现在很多知名的公司都在使用nginx。
Nginx应用场景
1、http服务器(静态网页展示)
2、虚拟主机。可以实现在一台服务器虚拟出多个网站。
3、反向代理,负载均衡。
下载地址:http://nginx.org/en/download.html
Windows环境
Windows下只需要解压就可以了,然后编写配置文件,这里windows下就简单的演示一下就可以了。
nginx反向代理
启动显示下面的提示表示nginx启动成功,我们也可以通过任务管理器查看
任务管理器两个进程
访问http://127.0.0.1:8888/logo.png路径可以获取到我们刚才的图片文件。这就简单的在Windows上实现了nginx的反向代理。
通过任务管理器关闭nginx则不能访问成功。
Linux环境
环境搭建
通过XFtp将nginx-1.6.3.tar.gz上传到/usr/local/nginx目录下。
安装gcc环境
Yum -y install gcc-c++
安装PCRE
PCRE(Perl Compatible Regular Expressions) 是一个Perl库,包括 perl 兼容的正则表达式库。nginx 的 http 模块使用 pcre 来解析正则表达式,所以需要在 linux 上安装 pcre 库,pcre-devel 是使用 pcre 开发的一个二次开发库。nginx也需要此库。命令:
yum install -y pcre pcre-devel
安装zlib
yum install -y zlib zlib-devel
安装openssl
yum install -y openssl openssl-devel
安装Nginx
解压我们得nginx压缩包
tar -zxvf nginx-1.6.3.tar.gz
进入到解压目录
cd nginx-1.6.3
编译
./configure
安装
make
make install
这里就可以将我们得安装包删除掉了
rm -rf nginx-1.6.3
rm -rf nginx-1.6.3.tar.gz
启动nginx
cd sbin/
./nginx
启动成功
访问IP地址+端口号80就可以访问我们的nginx
操作代码
启动命令:
/usr/local/nginx/sbin/nginx
重启:
/usr/local/nginx/sbin/nginx -s reload
停止:
/usr/local/nginx/sbin/nginx -s stop
Nginx配置文件
user nobody;worker_processes 1;
error_log logs/error.log; error_log logs/error.log notice; error_log logs/error.log info; pid logs/nginx.pid;events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
我们将html下的index.html默认文件内容稍作修改,然后重启nginx
重启命令(sbin目录下):./nginx -s reload
然后在访问。
(以下全在Windows中配置)
反向代理
我们放一张图片进去实现windows下相同的代理图片的功能。
C:\Windows\System32\drivers\etc修改一下hosts文件
最后增加一行(表示所有的mjxy.com的请求都转发到192.168.10.110)
192.168.10.110 www.mjxy.com
192.168.10.110 8081.mjxy.com
192.168.10.110 8082.mjxy.com
测试成功
这里修改一下我们的配置文件
反向代理(多个项目)
我们这里要实现一台电脑上面利用nginx代理三个位置。
我们在html下新建一个文件夹wwwroot
然后在建立三个文件夹8080/8081/8082,我们这里就利用三个html页面去代替我们的Web项目。
我们将原来的html下的index.html复制到对应的三个文件夹下,将内容简单的修改一下就可以了。
然后修改我们的配置文件(新增两个server)。
server {
listen 80;
server_name 8081.mjxy.com;
location / {
root html/wwwroot/8081;
index index.html index.htm;
}
}
server {
listen 80;
server_name 8082.mjxy.com;
location / {
root html/wwwroot/8082;
index index.html index.htm;
}
}
server {
listen 80;
server_name www.mjxy.com;
#access_log logs/host.access.log main;
location / {
root html/wwwroot/8080;
index index.html index.htm;
}
*************
访问效果
www.mjxy.com
8081.mjxy.com
8082.mjxy.com
负载均衡
为什么要使用负载均衡,首先就是要求项目是集群的情况下。
一、集群简介
(1) 什么是集群:集群是指一组计算机利用网络组成一个较大的计算机服务系统,这些计算机可以分布在一个机房,也可以分布在全国各地
(2) 为什么要使用集群:高性能、可伸缩性、高可用性、可管理性、......
(3) 集群的分类:负载均衡集群、高可用集群、高性能集群、网格计算集群
(4) 可实施集群的软件:Nginx 、LVS 、Haproxy 、Keepalived 、Heartbeat
(5) 可实施集群的硬件:F5 、Netscaler 、Radware 、A10
这里我们先删除掉我们刚才的配置。保留一个8080就好了。
这里我们在本地演示
配置负载均衡
upstream mjxyserver{
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
server {
listen 80;
server_name www.mjxy.com;
location / {
proxy_pass http://mjxyserver;
index index.html index.htm;
}
启动,通过127.0.0.1的域名www.mjxy.com进行访问。可以发现配置成功。
负载均衡机制
通过www.mjxy.com访问
轮训机制(负载均衡策略)
默认轮训
Ip绑定(每个访客固定访问一个后端服务器,有效的解决了Session共享的问题)
upstream backserver{
ip_hash;
server 192.168.10.111:80;
server 192.168.10.112:80;
}
权重
在配置后面加上weight=?;
upstream backserver{
server 192.168.10.111:80 weight=2;
server 192.168.10.112:80 weight=1;
}
可以发现A项目和B项目的出现频率为2:1
宕机解决办法
配置连接,发送信息,读取信息的等待时间,超过时间则换一个服务器(改为轮训方便测试)
server {
listen 80;
server_name www.mjxy.com;
location / {
proxy_pass http://mjxyserver;
index index.html index.htm;
proxy_connect_timeout 1;
proxy_send_timeout 1;
proxy_read_timeout 1;
}
}
Nginx实现防盗链
(配置表示所有的以mjxy.com的referer来的请求都可以访问)
location ~ .*.(jpg|jpeg|JPG|png|gif|icon)$ {
valid_referers blocked www.mjxy.com mjxy.com;
if ($invalid_referer) {
return 403;
}
}
将配置文件还原成刚开始那样
稍微修改一下html下的index页面,把一个A标签跳转到www.mjxy.com/mjxy/logo.png,这样就可以产生一个referer,随后我们在增加一个hosts跳转,直接访问图片出现403错误。
直接通过www.mjxy.com/mjxy/logo.png也是访问不到图片的,为什么呢?
因为是判断referer请求来源,直接访问是没有来源的。注意!!!!
访问referer页面http请求。
防止DDOS
限制请求速度
设置Nginx、Nginx Plus的连接请求在一个真实用户请求的合理范围内。比如,如果你觉得一个正常用户每两秒可以请求一次登录页面,你就可以设置Nginx每两秒钟接收一个客户端IP的请求(大约等同于每分钟30个请求)。
说明:区域名称为one(自定义),占用空间大小为10m,平均处理的请求频率不能超过每秒一次。
limit_req_zone $binary_remote_addr zone=one:10m rate=30r/m;
server {
limit_req zone=one;
listen 80;
server_name www.mjxy.com;
快速强行刷新
问:安全架构,面试官问你有什么解决安全的方法。答:Nginx反向代理:不暴露IP
使用Https防止抓包
搭建企业白黑名单,referer
防止模拟请求,XSS攻击,SQL注入,防止DDOS攻击
Nginx搭建网关接口解决跨域问题
什么是跨域?
跨域是浏览器的限制,不是我们开发的问题,我们只需要去解决跨域就好了。
什么是同一域中:同协议,同域名,同端口。路径可以不同
Html页面
<html>
<head>
<title>码家学院---Nginx解决跨域问题</title>
</head>
<body>
<p th:text="'MJXY Server : '+${port}"></p>
<img alt="" src="http://127.0.0.1:8080/logo.png" />
<script type="text/javascript" th:src="@{/js/jquery-3.3.1.min.js}"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
type : "GET",
url : "http://127.0.0.1:8080/msg",
success : function(data) {
alert(data);
},
error : function() {
alert("error");
}
});
});
</script>
</body>
</html>
配置文件
location /A {
proxy_pass http://127.0.0.1:8080/;
}
location /B {
proxy_pass http://127.0.0.1:8081/;
}
这样通过www.mjxe.com/A和www.mjxe.com/B就可以将两个服务器设置在同一域中。
Nginx高可用
什么是高可用
高可用一般指服务的冗余,一个服务挂了,可以自动切换到另外一个服务上,不影响客户体验。就是某个服务挂掉了,但是不影响用户的使用。
Keepalived介绍
Keepalived是一个免费开源的,用C编写的。
Keepalived的作用是检测服务器的状态,如果有一台web服务器宕机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。
集成KeepAlived
安装keepalived
地址:http://www.keepalived.org/download.html
解压安装:
tar -zxvf keepalived-1.2.18.tar.gz -C /usr/local/
yum install -y openssl openssl-devel(需要安装一个软件包)
cd keepalived-1.2.18/
./configure --prefix=/usr/local/keepalived
make
make install
加载系统服务
将keepalived安装成Linux系统服务,因为没有使用keepalived的默认安装路径(默认路径:/usr/local),安装完成之后,需要做一些修改工作:
首先创建文件夹,将keepalived配置文件进行复制:
mkdir /etc/keepalived
cp /usr/local/keepalived/etc/keepalived/keepalived.conf /etc/keepalived/
然后复制keepalived脚本文件:
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
ln -s /usr/local/sbin/keepalived /usr/sbin/
ln -s /usr/local/keepalived/sbin/keepalived /sbin/
可以设置开机启动:chkconfig keepalived on,到此我们安装完毕!
service keepalived start
service keepalived stop
如果启动失败的情况下处理方法
cd /usr/sbin/
rm -rf keepalived
cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
两台机器同样的配置,只是主节点要做更改。
配置文件
global_defs {
router_id bhz005 ##标识节点的字符串,通常为hostname
}
vrrp_script chk_nginx {
script "/etc/keepalived/nginx_check.sh" #运行脚本,脚本内容下面有,就是起到一个nginx宕机以后,自动开启服务
interval 2 #检测时间间隔
weight -20 #如果条件成立的话,则权重 -20
}
vrrp_instance VI_1 {
state MASTER #来决定主从BACKUP
interface ens33 # 绑定虚拟 IP 的网络接口,根据自己的机器填写
virtual_router_id 1229 # 虚拟路由的 ID 号,节点设置必须一样
mcast_src_ip 192.168.10.119 #填写本机ip
priority 100 # 节点优先级,主要比从节点优先级高
nopreempt # 优先级高的设置 nopreempt 解决异常恢复后再次抢占的问题
advert_int 1 # 组播信息发送间隔,两个节点设置必须一样,默认 1s
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
chk_nginx #执行 Nginx 监控的服务
}
virtual_ipaddress {
192.168.10.119 # 虚拟ip,这里配置自己的IP地址
}
}
脚本文件
这里我们的配置文件因为权限问题不能直接访问脚本文件,需要赋予读取权限
chmod 777 nginx_check.sh
A=ps -C nginx ¨Cno-header |wc -l
if [ $A -eq 0 ];then
/usr/local/nginx/sbin/nginx
sleep 2
if [ ps -C nginx --no-header |wc -l
-eq 0 ];then
killall keepalived
fi
fi
虚拟IP
然后就可以帮我们自动重启Nginx了
测试自动重启
Session共享的解决方案
学习完了Redis和Nginx,我们就可以完成Session共享的解决方案
集群情况下session会产生什么问题?
服务器A和服务器B
什么是Session会话机制?
假设你访问网页时就像逛澡堂,第一次进去你是没有钥匙的,这个时候你交了钱服务台就分配一把钥匙给你,你走到哪里都要带上,因为这是你身份的唯一标识,接下来你用这把钥匙可以去打开一个专有的储物柜存储你的衣物,游完泳,你再用钥匙去打开柜子拿出衣物,最后离开游泳池时,把钥匙归还,你的这次游泳的过程就是一次session,或者叫做会话,在这个例子中,钥匙就是session的key,而储物柜可以理解为存储用户会话信息的介质。
Session存放在哪里?
存储在服务器的内存中,tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,redis等。客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session。
Session共享解决方案
1、用Nginx 做的负载均衡可以添加ip_hash这个配置,从而使同一个ip的请求发到同一台服务器
2、利用数据库同步session
3、利用cookie同步session数据原理图如下
4、使用Redis存放Session
Session共享解决
重现问题
SpringBoot
Pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
Application.yml
server:
port: 8080
Controller
@RestController
public class IndexController {
@Value("${server.port}")
private String PORT;
@RequestMapping("/set")
public String setSession(String key, String value, HttpSession session) {
session.setAttribute(key, value);
return "Port:" + PORT + "--SetSession Success==>key:" + key + "--value:" + value;
}
@RequestMapping("/get")
public String getSession(String key, HttpSession session) {
String value = (String) session.getAttribute(key);
return "Port:" + PORT + "--GetSession Success==>key:" + key + "--Get Value:" + value;
}
@RequestMapping("/del")
public String delSession(String key, HttpSession session) {
session.removeAttribute(key);
return "Port:" + PORT + "--DelSession Success==>key:" + key;
}
}
启动8080和8081端口,两边Session根本不会共享。
思考:怎么利用Nginx解决这种问题?例外有什么缺点。
答:ip_hash绑定,使用来自同一请求地址用户始终访问同一服务器,思考缺点:当前服务器万一宕机了,用户就不能正常访问了。缺点就是服务器重启之后Session全部失效。使用Redis解决Session共享(实战解决方法)
启动redis
./redis-server /usr/local/redis/etc/redis.conf
Pom新增
<!--spring boot redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
<!--spring session与redis关联配置 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
Session配置
/**
- @author 作者 :码家学院 讲师 廖祥 qq:438944209
- @version 创建时间:2018年1月28日 下午9:10:07 说明:{ }
*/
//这个类用配置redis服务器的连接
//maxInactiveIntervalInSeconds为SpringSession的过期时间(单位:秒)
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class SessionConfig {
// 冒号后的值为没有配置文件时,制动装载的默认值
@Value("${redis.hostname:192.168.10.100}")
String HostName;
@Value("${redis.port:6379}")
int Port;
@Bean
public JedisConnectionFactory connectionFactory() {
JedisConnectionFactory connection = new JedisConnectionFactory();
connection.setPort(Port);
connection.setHostName(HostName);
return connection;
}
}
Session初始化配置
// 初始化Session配置
public class SessionInitializer extends AbstractHttpSessionApplicationInitializer {
public SessionInitializer() {
super(SessionConfig.class);
}
}
产生Session过后可以查看redis做了记录。