Nginx动静分离负载均衡

前期准备javascript

使用Debian环境。安装Nginx(默认安装),一个web项目,安装tomcat(默认安装)等。php

Nginx.conf配置css

1 # 定义Nginx运行的用户 和 用户组 若是对应服务器暴露在外面的话建议使用权限较小的用户 防止被入侵
 2 # user www www;
 3 
 4 #Nginx进程数, 建议设置为等于CPU总核心数
 5 worker_processes 8;
 6 
 7 #开启全局错误日志类型
 8 error_log /var/log/nginx/error.log info;
 9 
10 #进程文件
11 pid /var/run/nginx.pid;
12 
13 #一个Nginx进程打开的最多文件描述数目 建议与ulimit -n一致
14 #若是面对高并发时 注意修改该值 ulimit -n 还有部分系统参数 而并不是这个单独肯定
15 worker_rlimit_nofile 65535;
16 
17 events{
18 #使用epoll模型提升性能
19 use epoll;
20 #单个进程最大链接数
21 worker_connections 65535;
22 }
23 
24 http{
25 #扩展名与文件类型映射表
26 include mime.types;
27 #默认类型
28 default_type application/octet-stream;
29 sendfile on;
30 tcp_nopush on;
31 tcp_nodelay on;
32 keepalive_timeout 65;
33 types_hash_max_size 2048;
34 #日志
35 access_log /var/log/nginx/access.log;
36 error_log /var/log/nginx/error.log;
37 #gzip 压缩传输
38 gzip on;
39 gzip_min_length 1k;  #最小1K
40 gzip_buffers 16 64K;
41 gzip_http_version 1.1;
42 gzip_comp_level 6;
43 gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
44 gzip_vary on;
45 #负载均衡组
46 #静态服务器组
47 upstream static.zh-jieli.com {
48 server 127.0.0.1:808 weight=1;
49 }
50 #动态服务器组
51 upstream zh-jieli.com {
52 server 127.0.0.1:8080;
53 #server 192.168.8.203:8080;
54 }
55 #配置代理参数
56 proxy_redirect off;
57 proxy_set_header Host $host;
58 proxy_set_header X-Real-IP $remote_addr;
59 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
60 client_max_body_size 10m;
61 client_body_buffer_size 128k;
62 proxy_connect_timeout 65;
63 proxy_send_timeout 65;
64 proxy_read_timeout 65;
65 proxy_buffer_size 4k;
66 proxy_buffers 4 32k;
67 proxy_busy_buffers_size 64k;
68 #缓存配置
69 proxy_cache_key '$host:$server_port$request_uri';
70 proxy_temp_file_write_size 64k;
71 proxy_temp_path /dev/shm/JieLiERP/proxy_temp_path;
72 proxy_cache_path /dev/shm/JieLiERP/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=5d max_size=1g;
73 proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie;
74 
75 server{
76 listen 80;
77 server_name erp.zh-jieli.com;
78 location / {
79 index index; #默认主页为 /index
80 #proxy_pass http://jieli;
81 }
82 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
83 proxy_cache cache_one;
84 proxy_cache_valid 200 304 302 5d;
85 proxy_cache_valid any 5d;
86 proxy_cache_key '$host:$server_port$request_uri';
87 add_header X-Cache '$upstream_cache_status from $host';
88 proxy_pass http://static.zh-jieli.com;
89 #全部静态文件直接读取硬盘
90 #   root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
91 expires 30d; #缓存30天
92 }
93 #其余页面反向代理到tomcat容器
94 location ~ .*$ {
95 index index;
96 proxy_pass http://zh-jieli.com;
97 }
98 }
99 server{
100 listen 808;
101 server_name static;
102 location / {
103 
104 }
105 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
106 #全部静态文件直接读取硬盘
107 root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
108 expires 30d; #缓存30天
109 }
110 }
111 }

基本配置这个文件,就能够实现负载均衡了。可是里面的各类关系要了解就比较麻烦了。html

 

实例讲解前端

如今假使有一台电脑192.168.8.203这台电脑,上面部署了Tomcat,里面8080端口有J2EE的服务,经过浏览器能够正常浏览网页。如今有一个问题tomcat是一个比较全面的web容器,对静态网页的处理,应该是比较费资源的,特别是每次都要从磁盘读取静态页面,而后返回。这中间会消耗Tomcat的资源,可能会使那些动态页面解析性能影响。秉承Linux哲学,一个软件只作一件事的原则。Tomcat就应该只处理JSP动态页面。这里就用到之前了解的Nginx来进行反向代理。第一步代理,实现动静网页分离。这个很简单的java

1      worker_processes 8;
2 
3 pid /var/run/nginx.pid;
4 
5 worker_rlimit_nofile 65535;
6 
7 events{
8 use epoll;
9 worker_connections 65535;
10 }
11 
12 http{
13 include mime.types;
14 default_type application/octet-stream;
15 sendfile on;
16 tcp_nopush on;
17 tcp_nodelay on;
18 keepalive_timeout 65;
19 types_hash_max_size 2048;
20 
21 proxy_redirect off;
22 proxy_set_header Host $host;
23 proxy_set_header X-Real-IP $remote_addr;
24 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
25 client_max_body_size 10m;
26 client_body_buffer_size 128k;
27 proxy_connect_timeout 65;
28 proxy_send_timeout 65;
29 proxy_read_timeout 65;
30 proxy_buffer_size 4k;
31 proxy_buffers 4 32k;
32 proxy_busy_buffers_size 64k;
33 
34 server{
35 listen 80;
36 server_name xxx.com;
37 location / {
38 index index; 
39 }
40 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
41 proxy_pass http://192.168.8.203:8080;
42 expires 30d; 
43 }
44 location ~ .*$ {
45 index index;
46 proxy_pass http://192.168.8.203:8080;
47 }
48 }
49 }

修改nginx的配置文件 /etc/nginx/nginx.conf 默认有个配置文件的。其实大部分都差很少,关键仍是server段的设置。这里我设置server段如上所示,其余段复制就能够了。server段里面的解释以下:第35行为监听本机80端口。37-39行表示默认主页,这里的默认主页我是index.jsp 对应到我项目中是一个index。 这里根据须要能够改成 node

 

index index.jsp index.html index.htm index.php

 

具体可参考其余文章。 关键的第40行,这个是正则匹配,网上也有不少介绍。这里匹配我项目中用到的全部静态网页后缀。第41行是代理地址。这里我代理到个人web应用中。expires 30d缓存为30天,这里的缓存是对应到前端页面,用户的Cache-Control字段,nginx

第44行中那个正则是匹配无后缀的页面。我项目中jsp页面是无后缀的。这里能够根据须要进行修改。一样代理到192.168.8.203:8080这里。到这里你可能会问,我艹,这有毛意思啊?固然不是这样了。简单的实现静动分离,咱们能够把第41行进行修改,改成web

root   /var/lib/tomcat7/webapps/JieLiERP/WEB-INF

 

表示不代理,直接从本地磁盘拿。经过查tomcat日志能够看到静态页面是没有访问到的。但这样又有一个问题。这样的灵活性很差,对下面要讲到的内存缓存和集群部署来讲都是不友好的,因此又有了下面的这种写法。再写一个server段。redis

1 server{
2 listen 808;
3 server_name static;
4 location / {
5 
6 }
7 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
8 #全部静态文件直接读取硬盘
9 root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
10 expires 30d; #缓存30天
11 }
12 }

此次监听808端口,而后上上面的代码41行就能够修改成 proxy_pass http://192.168.8.203:808了,到这里就实现了动静分离了。若是多台服务器,就修改对应的ip就能够了。若是发现链接不上的,要检查一下防火墙,权限等外部问题,这个配置是这样的。

若是单纯这样的话,咱们会发现页面直接传输过于占用带宽。对应web的优化,这里想到的是经过对页面进行gzip压缩,而后传到用户那里,再解压,这样能够有效的减小带宽。这里就会用到Nginx 的gzip模块了。默认的Nginx是集成有gzip模块的。只需在http段增长下面配置便可。

1 gzip on;
2 gzip_min_length 1k;  #最小1K
3 gzip_buffers 16 64K;
4 gzip_http_version 1.1;
5 gzip_comp_level 6;
6 gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
7 gzip_vary on;

 

给个首页看看效果

不要在乎请求数不同,那两个请求是谷歌插件来的。不用以为我在骗你。

做为假使有不少人访问的网站来讲,缓存确定是很重要的东西了。一开始是想经过插件,让Nginx和Redis进行合成,而后Nginx使用Redis来缓存的,可是发现配置起来很麻烦,还要本身下载插件,从新编译Nginx,比较麻烦,因此这里以为用Nginx自带的缓存也是不错的选择。虽然效率比不上redis,可是有仍是比没有好。Nginx默认的缓存是磁盘文件系统的缓存,而不是像Redis那样的内存级别的缓存。一开始我觉得Nginx就只有这样。后来查了写资料,才知道是我太天真了,对Linux不是很了解致使的。Linux的一切皆文件。原来咱们能够把文件缓存到内存对应的Linux文件系统中。我说的可能比较难以理解,请自行搜索/dev/shm 这个文件目录。咱们把文件缓存到这个文件目录里,其实就至关与内存的缓存了。只不过仍是靠文件系统管理。因此比不上自定义格式的Redis那样的内存缓存。

在http段进行基本配置

1 #缓存配置
2 proxy_cache_key '$host:$server_port$request_uri';
3 proxy_temp_file_write_size 64k;
4 proxy_temp_path /dev/shm/JieLiERP/proxy_temp_path;
5 proxy_cache_path /dev/shm/JieLiERP/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=5d max_size=1g;
6 proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie

  

 

1 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
2 proxy_cache cache_one;
3 proxy_cache_valid 200 304 302 5d;
4 proxy_cache_valid any 5d;
5 proxy_cache_key '$host:$server_port$request_uri';
6 add_header X-Cache '$upstream_cache_status from $host';
7 proxy_pass http://192.168.8.203:808;
8 
9 expires 30d; #缓存30天
10 }

通过这两个的配置就基本能实现了,这里说几个注意项,也是困扰我好久的问题。上面第一段代码第6行,proxy_ignore_headers 若是web项目中的html的head头里面指定

1 <meta http-equiv="pragma" content="no-cache">
2 <meta http-equiv="cache-control" content="no-cache">
3 <meta http-equiv="expires" content="0">

这些不缓存的话,就要加上proxy_ignore_headers的配置项了。还有一点就是/dev/shm下面的文件系统权限默认只给root用户,因此要chmod 777 -R /dev/shm 这样不是很安全的作法,若是实际上线能够给定某个用户组,关于用户组的设置是配置的第一行

 

user www www;

 

上面第二段代码的第6行是增长一个header字段方便查看是否击中缓存。

咱们rm -rf /dev/shm/JieLiERP/proxy_* 下面的全部文件(注意这里若是是进行屡次测试的话要nginx -s reload 从新读取配置或重启服务,由于你rm -rf只是删除了缓存文件,可是缓存的结构信息还在nginx进程里面,结构还在,若是不重启的话,是会出现访问不到的)

因此要记得重启哦。下面是运行效果

第一次访问

第二次访问,在浏览器中Ctrl+Shift+R 强制刷新

到这里就能够看到效果了。咱们查看一下/dev/shm这个里面

到这里已经快结束了。最后也是比较关键的一个技术点,就是集群,集群,集群。这个就要用到upstream了,看到最开头的配置文件了吗,就是那个

负载均衡组
#静态服务器组
upstream static {
server 127.0.0.1:808 weight=1;
server 192.168.8.203:808 weight=1;
}


#动态服务器组
upstream dynamic {
server 127.0.0.1:8080;
#server 192.168.8.203:8080;
}

上面那个就是集群组了。upstream是关键字,static 和 dynamic是两个服务器集群组的名称。以第一个为例,server 127.0.0.1:808 是服务器地址,后面的weight=1 是权重。有多个就写多个。亲测试过,集群中的一个坏了,不影响系统运行。至于更多的轮询规则,能够参考网上更多的资料。这里很少说。至于怎么使用呢? proxy_pass http://192.168.8.203:808 改成 proxy_pass http://static; 这样便可实现均衡。

到这里就结束了。把上面各个部分根据本身需求配置起来就能够实现单机房负载均衡了。 上面这种作法有一个缺点就是在前面的那一台nginx若是当机,后面因此机器就失去了被访问的能力了,因此须要在前面实现多个nginx多机房的负载。关于这个就是另一个话题了。目前尚未研究。之后有机会再说了。

上面动态服务器组若是是那种须要保存用户状态的话,会有问题,就是session问题,好比我在server1进行登陆后,下一次动态服务器组进行轮询后可能分配到server2,就会形成要从新登陆。治标的办法是,配置轮询规则,根据用户请求的IP进行Hash,而后分配对应的服务器。具体配置以下:

1 upstream dynamic{
2 ip_hash;
3 server 127.0.0.1:8080;
4 server 192.168.0.203:8080;
5 }

 

这样就能够实现一个用户对应一个服务器节点。这样就不会有重复登陆的问题。

另外一种治本的办法是,利用缓存系统进行session的统一存储管理。具体的作法我尚未试验过,参考资料有相关的文章,能够了解一下。

Nginx增长SSL功能,一样的Nginx默认是有SSL模块功能,咱们不用额外安装,只须要简单的配置就能够了。首先咱们先来生成一些必要的证书。制做的过程仍是比较简单的

1 #制做CA证书
2 openssl genrsa -des3 -out ca.key 2048
3 openssl req -new -x509 -days 7305 -key ca.key -out ca.crt
4 
5 #生成Nginx服务器所需证书,并使用CA签名
6 openssl genrsa -des3 -out client.key 1024
7 openssl req -new -key client.key -out client.csr
8 openssl x509 -req -in client.csr -out client.pem -signkey client.key -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
9 
10 #取消证书密码
11 openssl rsa -in client.key -out client.key.unsecure

 下面就是配置Nginx了,咱们能够把须要用到的client.pem, client.pem, client.key,unsecure这三个文件放到Nginx的一个目录下,剩下的Nginx配置以下:

 

1 server{
2 server_name localhost;
3 listen 443 ssl;
4 root html;
5 location / {
6 index index.html index.html;
7 }
8 ssl on;
9 ssl_certificate keys/client.pem;
10 ssl_certificate_key keys/client.key.unsecure;
11 }

重启Nginx,咱们就能够访问Https网站了。 可是他喵的出现这个

 

这个是没有什么问题,具体缘由是这个CA证书要获得承认。因此咱们上面本身生成的https证书,只是本身生成的,若是要变成下面这种,就须要花钱购买了,剩下的这个本身上网解决。(虽然本身生成的证书能够用,可是仍是抵挡不了DNS欺骗,因此这种不安全证书,跟没有实际上是同样的。不过听说这样能够阻止运营商劫持。)

增长一个,就是在咱们输入http链接时自动跳转到安全的https链接。这个仍是比较实用的。方法仍是有多种的,具体能够看参考资料里面的博客。我是使用下面这一种,我以为是比较简单的,代码改动比较少的。就是对80端口进行代理转发。

1 server{
2 server_name localhost;
3 listen 80;
4 rewrite ^(.*)$ https://$host$1 permanent;
5 }
相关文章
相关标签/搜索