分布式架构——第13篇:Nginx反向代理与负载均衡

本文介绍一下使用Nginx反向代理来做负载均衡。使用十分简单,只需要配置upstream并选择负载均衡策略,再配置server反向代理功能就全部搞定了。

架设Nginx服务

直接使用Docker启动一台虚拟Nginx服务器。

$ sudo docker run --net=pub_net --ip=192.168.1.13 --name macvlan_ngx1 --restart always -d nginx

配置Nginx服务——反向代理与负载均衡

Nginx的主配置文件位于/etc/nginx/nginx.conf中。默认内容如下:

user  nginx;
worker_processes 1;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;


events {
worker_connections 1024;
}


http {
include /etc/nginx/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 /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

include /etc/nginx/conf.d/*.conf;
}

可以很明显的看到/etc/nginx/conf.d/*.conf中的所有.conf后缀的都会被自动加载作为配置文件。为此,自定义配置文件时,直接在conf.d目录下新建后缀为.conf的文件即可。

以下给出一份配置文件,主要用于NginxTomcat转发的负载均衡。我在Docker中虚拟出了5台Tomcat服务器(192.168.1.[19-23])。其中,由两台Tomcat服务器组成了Web Server 1服务器组(采用ip_hash算法,就是根据ip做转发)。用3台Tomcat组成了Web Server 2服务器组(设置服务器转发权重)。 e.g.

upstream webserver1 {
ip_hash;
server 192.168.1.19:8080;
server 192.168.1.20:8080;
}

upstream webserver2 {
server 192.168.1.21:8080 weight=5;
server 192.168.1.22:8080 weight=3;
server 192.168.1.23:8080 weight=2;
}

server {
listen 80;
server_name tomcat1.com tomcat2.com;

location / {
proxy_pass http://webserver1;
}
location /hello {
proxy_pass http://webserver1/hello;
}
}

server {
listen 80;
server_name tomcat3.com tomcat4.com tomcat5.com;

location / {
proxy_pass http://webserver2;
}
location /world {
proxy_pass http://webserver2/world;
}
}

server {
listen 80;
server_name pc.com;

location / {
proxy_pass https://www.baidu.com/;
}
}

一些注意事项

有几点需要注意的,Nginx收到请求之后,会获取请求的Host字段,然后根据Host内容匹配server_name然后转发给不同的server。转发时直接使用proxy_pass指令即可,路径中可以写upstream以实现负载均衡。

下面摘录了百度的一个请求内容。

GET / HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7,ru;q=0.6
Cookie: //...

正因为这样,我曾尝试着在发起Http请求的时候动态设置Host字段,但是一直没成功(总是被总动纠正为当前的url)。后来查阅相关资料说是Http协议不让设置Host字段。

那么,如何使用上Nginxserver_name机制?这里一般就只能用DNS解析了,如果正式买了域名的话,比如baidu.com,会由域名注册商提供DNS解析。当然,这里只是测试,可以直接修改本地的hosts文件,设置域名和IP的映射关系,以达到DNS解析的效果。

配置hosts文件

由于,这里只启动了一台IP为192.168.1.13的Nginx服务器,那么在我的开发机(Windows 10,192.168.1.2)上的C:\Windows\System32\drivers\etc\hosts文件中可以做以下映射。

192.168.1.13 tomcat1.com
192.168.1.13 tomcat2.com
192.168.1.13 tomcat3.com
192.168.1.13 tomcat4.com
192.168.1.13 tomcat5.com
192.168.1.13 pc.com

浏览器访问Nginx服务器

好了,测试Nginx配置文件的有效性(这里-t后不需要添加任何内容,不要写成nginx -t /etc/nginx/nginx.conf):

# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

重新载入Nginx

# nginx -s reload
2018/10/28 14:18:44 [notice] 24#24: signal process started

此时,就可以在开发机的浏览器中访问Nginx服务器,查看具体的反向代理与负载均衡效果了:

http://tomcat1.com/
http://tomcat2.com/hello
http://tomcat3.com/world
http://pc.com/

References: [1] https://blog.csdn.net/wy757510722/article/details/75267431?utm_source=blogxgwz0 [2] https://blog.csdn.net/qq_21768483/article/details/78339450?utm_source=blogxgwz1 [3] https://www.w3cschool.cn/nginx/nginx-d1aw28wa.html [4] https://blog.csdn.net/u012486840/article/details/52787282 [5] https://chrome.google.com/webstore/category/extensions?hl=zh-CN [6] http://www.hangge.com/blog/cache/detail_1697.html [7] https://www.telerik.com/fiddler [8] https://blog.phpgao.com/nginx_config.html [9] https://www.v2ex.com/t/305568 [10] https://js8.in/2011/10/29/%E6%A3%80%E6%9F%A5nginx%E9%85%8D%E7%BD%AE%EF%BC%8C%E9%87%8D%E8%BD%BD%E9%85%8D%E7%BD%AE%E4%BB%A5%E5%8F%8A%E9%87%8D%E5%90%AF%E7%9A%84%E6%96%B9%E6%B3%95/