为了账号安全,请及时绑定邮箱和手机立即绑定

Nginx中高级

标签:
Linux

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;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
#                  '$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)

nginx

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;

charset koi8-r;
    #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="" class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="http://127.0.0.1:8080/logo.png" />
<script type="text/javascript" th:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="@{/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
}

定义虚拟路由,VI_1 为虚拟路由的标示符,自己定义名称

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 块加入 instance 配置块
track_script {
    chk_nginx #执行 Nginx 监控的服务
}
virtual_ipaddress {
    192.168.10.119 # 虚拟ip,这里配置自己的IP地址
}

}

脚本文件
这里我们的配置文件因为权限问题不能直接访问脚本文件,需要赋予读取权限
chmod 777 nginx_check.sh

!/bin/bash

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做了记录。

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
112
获赞与收藏
542

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消