专栏名称: 马哥Linux运维
马哥linux致力于linux运维培训,连续多年排名第一,订阅者可免费获得学习机会和相关Linux独家实战资料!
目录
相关文章推荐
运维  ·  再见,CDN 巨头:Akamai 宣布 ... ·  3 天前  
51好读  ›  专栏  ›  马哥Linux运维

Nginx动静分离实现负载均衡

马哥Linux运维  · 公众号  · 运维  · 2018-06-27 18:00

正文

来源:程序员面试

ID:mvpjob


前期准备

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

Nginx.conf配置


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 1 k;  #最小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 }


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

实例讲解

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


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。 这里根据需要可以改为


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


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

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


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


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


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 30 d; #缓存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这个里面







请到「今天看啥」查看全文


推荐文章
晚安少年  ·  VOL.556 你忙你的吧
8 年前
禅茶一味  ·  厚道,才是正道
8 年前
禅语心苑  ·  人算,天算,佛算
7 年前