[05] nginx: TCP / forward / reverse proxy / load balancing

EDITORIAL words

 

In our daily work, it is impossible that all the services are simple static HTML pages, nginx as a lightweight WEB server, in fact, we use it for more places or as the entrance to our website. Whether you are a backend interface, or front page, we let the user requests to the service. There are several reasons why:

1. Centralized management more manageable.

2. external services are needed public IP, you need the bandwidth, if each machine specially configured with a public IP and bandwidth, it is too wasteful, you can look at a few cloud service providers the bandwidth charges I recently finishing:

The higher the bandwidth, the higher the cost, this is not high geometric growth.

3. Our service is generally not a single point of service, then the front and rear ends can not communicate, how to configure addresses, each configuration? It will not be too much trouble spot.

4. In our generation servers, similar redis / server database such networking is generally not allowed for security, but we do not always have to log in to the server to check the data on it?

This is the simple reason, then we have to talk to several agents, by the way their application scenarios, of course, this design is sufficient for small and medium sized companies, after all, manufacturers have not been, do not know their specific architecture and implementation.

 

 

TCP proxy

 

TCP proxy before saying we certainly still must first understand what the agent is next?

Proxy ( Proxy ) is actually a transit point for network information, we use a diagram to represent:

Such a scenario, the user on the outside, it is possible to access to the public network via the cluster cloud provider server has a public IP, but other servers are within the cluster does not have the public IP address, the public network, we were unable to access, but there are just public IP server in the cluster, its network card and these no public IP network can communicate with machines, which means that the machine can not only communicate with the user, and they can back-end cluster communication. Then we have to think of ways to access the user behind the cluster, so that the server has a public IP address to help convey the look, then, as a middleman, to achieve mutual messenger between users and back-end clusters, so the public IP network machine becomes a proxy server.

 

That is what TCP proxy?

In our daily visit WEB application, we are using the http: //, https: //. But some services than http, such as MySQL this connection, this is clearly not the WEB service, so we can not be like WEB proxy service agent as it is. And such service is TCP service, we have exclusive use of TCP proxy.

We also, for example TCP proxy MySQL to specifically talk about how to use the configuration.

We have compiled in time to join the  --with-stream argument, which is that we use a proxy indispensable.

Similarly, we in the main configuration file by nginx.conf include configuring a separate directory for the configuration files are placed TCP configuration:

It is worth noting that, TCP is not the HTTP proxy service, and include all our previous position is not the same, we have to put the outer layer of http:

user  root;
...
http {
    ...
}
stream {
    include tcp/*.conf;
}

Our new tcp directory: I'm here for the convenience of using the root user directly using nginx

mkdir /data/services/nginx/conf/tcp

Increase MySQL proxy configuration file in the directory: MySQL-Proxy-demo.conf

upstream MYSQL-PROXY-DEMO {
    hash $remote_addr consistent;
    server 192.168.10.204:3306;
}

server {
    listen  5000;
    proxy_connect_timeout   10s;
    proxy_timeout   300s;
    proxy_pass  MYSQL-PROXY-DEMO;
}

Brief description:

1. In nginx, if the agent requires a plurality of machines to the rear end, to the need to use upstream, MYSQL Based-the PROXY-the DEMO are taken upstream to the name, the only requirement.

2. hash xxx is a scheduling model, of course, just write a server record here, all the other nodes in the scheduling problem does not exist.

3. server xxx is a need for a proxy records, each a server.

Similarly 4. server segment and http WEB services, but does not require server_name.

5. proxy_connect_timeout the connection timeout, proxy_timeout agent timeout.

6. proxy_pass, the most critical one proxy, the proxy that we named the port to which service or which upstream. It will be used later.

 

Nginx reload this time we test the database connection:

可以看到,我们成功的使用代理服务器的 IP + 端口通过 Navict 连接到了其它主机的 MySQL 数据库。

 

 

正向代理

 

正向代理不是我们使用的重点,因为在日常的使用中用的并不多,但是在某些特殊的场景下很有用。

比如有个局域网用户,无法访问互联网,但是局域网中另外一台机器却能够访问到互联网,所有我们可以通过那台机器作为代理去访问互联网。

正向代理的好处在于能够对需要访问的网站隐藏用户的真实信息。

 

这是系统为我提供的解决方案,但是并不是很好用,如果你想直接使用,请直接跳到后面第三方模块搭建正向代理

我们在 vhosts 目录下新建配置:forward-proxy-demo.conf

server {
    resolver 8.8.8.8;
    access_log off;
    listen 6080;
    location / {
        proxy_pass $scheme://$http_host$request_uri;
        proxy_set_header HOST $http_host;

        # 配置缓存大小,关闭磁盘缓存读写减少I/O,以及代理连接超时时间
        proxy_buffers 256 4k;
        proxy_max_temp_file_size 0;
        proxy_connect_timeout 30;

        # 配置代理服务器 Http 状态缓存时间
        proxy_cache_valid 200 302 10m;
        proxy_cache_valid 301 1h;
        proxy_cache_valid any 1m;
        proxy_next_upstream error timeout invalid_header http_502;
    }
}

简单说明:

红色部分为核心配置,这里我们直到了,在 nginx 中我们是可以通过 proxy_set_header 来处理请求头的。

 

我们在另外一台不能上网的机器上增加配置:

重载 nginx 后我们在不能上网的机器上执行 curl 百度:

curl -I --proxy 192.168.100.111:6080 http://www.baidu.com

结果如下:

当然我们也可以将代理配置定义成环境变量:

export http_proxy=http://192.168.100.111:6080

这样就能直接执行:

 

 

第三方模块搭建正向代理

 

当然,上面的配置都是针对 HTTP 的,对于 HTTPS 代理或者说整个正向代理,我们推荐使用第三方模块:ngx_http_proxy_connect_module

GITHUB 地址:

https://github.com/chobits/ngx_http_proxy_connect_module

将下载的 zip 包上传到服务器,重新编译 nginx,具体方法参考前面的动态添加模块:

https://www.cnblogs.com/Dy1an/p/11227796.html

1. 安装依赖:

yum install -y patch

 

2. 解压打补丁,编译:

从 GITHUB 上面,我们可以看到各个版本的 nginx 对应的补丁版本:

cd /data/packages/nginx
unzip ngx_http_proxy_connect_module-master.zip
cd nginx-1.16.0/
patch -p1 < /data/packages/nginx/ngx_http_proxy_connect_module-master/patch/proxy_connect_rewrite_101504.patch

编译不安装:

./configure --prefix=/data/services/nginx \
--user=nginx \
--group=nginx \--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-http_secure_link_module \
--with-http_flv_module \
--with-http_ssl_module \
--with-http_mp4_module \
--with-stream \
--with-http_realip_module \
--with-http_v2_module \
--with-http_sub_module \
--with-http_image_filter_module \
--with-pcre=/data/packages/nginx/pcre-8.43 \
--with-openssl=/data/packages/nginx/openssl-1.1.1c \
--with-zlib=/data/packages/nginx/zlib-1.2.11 \
--add-module=/data/packages/nginx/nginx-upload-module-master \
--add-module=/data/packages/nginx/nginx-upstream-fair-master \
--add-module=/data/packages/nginx/ngx_cache_purge-master \
--add-module=/data/packages/nginx/ngx-fancyindex-master \
--add-module=/data/packages/nginx/echo-nginx-module-master \
--add-module=/data/packages/nginx/ngx_http_proxy_connect_module-master

# 编译
make

 

3. 备份替换旧版:

# 备份
mv /data/services/nginx/sbin/nginx  /data/backup/nginx/nginx_$(date +%F)

# 更新
cp /data/packages/nginx/nginx-1.16.0/objs/nginx /data/services/nginx/sbin/

# 查看
/data/services/nginx/sbin/nginx -V

如图:

 

4. 添加 nginx 正向代理配置:

server {
    listen       6080;
    resolver 202.96.128.166;
    resolver_timeout 30s;

    # 代理配置
    proxy_connect;
    proxy_connect_allow            443 563;
    proxy_connect_connect_timeout  10s;
    proxy_connect_read_timeout     10s;
    proxy_connect_send_timeout     10s;

    location / {
        proxy_pass http://$host;
        proxy_set_header Host $host;
    }
}

重载配置访问测试:

curl -I --proxy 192.168.100.111:6080  http://www.baidu.com
curl -I --proxy 192.168.100.111:6080  https://www.alipay.com

HTTP 访问结果:

HTTPS 访问结果:

当然,我们也可以设置环境变量:

export http_proxy=http://192.168.100.111:6080
export https_proxy=http://192.168.100.111:6080
no_proxy="localhost,127.0.0.1,localaddress,.localdomain.com" 

最后,小结一下:正向代理配置虽然能够满足我们的一定需求,但是有些时候不是很稳定,包括在配置过程中,有时候并不能一次就能访问成功,需要多测试几次。

 

 

反向代理 / 负载均衡

 

反向代理一直是我们 nginx 服务配置的重中之重,我们工作的项目中大部分其实都是围绕着反向代理展开的。如果你用 nginx,你说你没有配置过静态资源 WEB 我相信,但是你没有用过反向代理,那你一定不是做运维的。

那什么是反向代理?

这需要我们和正向代理结合起来理解,我们之前正向代理的时候是我们代理别人的服务让我们能够访问到。

那么反向代理就是代理我们的服务让别人能够访问到,是不是一下子就清晰了。

我们本次测试环境用到了三台机器,一台是我们的 nginx,另外两台是安装了 tomcat 服务的服务器。我们要实现以下图示:

用户访问 nginx 的 8090 端口调度到后端的 TOMCAT 8080 上面去。

至于 TOMCAT 怎么安装部署这里就不做过多说明,这里做了个小处理,在 TOMCAT webapps 下面默认 ROOT 项目的 index.jsp 文件增加了本机 IP 用于区分:

此时我们启动两个 TOMCAT 访问测试:

节点1结果:

 

节点2结果:

 

在 nginx 的 vhosts 目录下增加如下配置:reverse-proxy-demo.conf 

upstream REVERSE-PROXY-DEMO {
    ip_hash;
    server 192.168.100.112:8080 weight=1 max_fails=3 fail_timeout=10s;
    server 192.168.100.113:8080 weight=1 max_fails=3 fail_timeout=10s;
} 

server {
    listen      8090;
    server_name localhost;
    
    location / {
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_connect_timeout 30;
        proxy_send_timeout 30;
        proxy_read_timeout 30;
        proxy_pass http://REVERSE-PROXY-DEMO;
    }
}

如 TCP 代理一般,TCP 代理其实也是反向代理的一种,我们定义的 upstream 的名称要求唯一。

重载 nginx 访问测试:

可以看到请求被分配到了 100.113 这台机器上面去了!

 

我们之前就在使用 upstream,但是 upstream 到底是啥我们一直没说,其实 upstream 就是负载均衡。

从字面上的意思就可以理解,负载均衡就是均衡的,按照特定的调度算法,将请求调度到指定的节点(upstream server)。

upstream 配置说明:

1. nginx 负载均衡调度算法加上我们安装的 fair 模块,大致有以下 4 种:

调度算法 说明
权重轮询(默认) 按照顺序逐一分配到不同的后端。自动剔除失败的机器,使访问不受影响。
ip_hash 每个请求按照 IP 的 Hash 结果分配,使来自同一 IP 的固定访问到同一后端。能解决部分程序 session 没共享的问题
fair 更智能的算法,可以根据页面大小和加载速度进行智能负载,响应快的优先分配。
url_hash 需要按照 nginx hash 模块,按照访问的 URL 定向到某个机器上,能提升后端缓存服务器的效率。

日常用到比较多的就是前三个。

 

2. server 后面的参数:

参数 说明
weight 分配到请求权重,权重比例多高分配到请求的机会越大。
max_fails 最大的失败连接次数。
fail_timeout 等待请求的目标服务器响应的时长。
backup 当所有机器都 down 掉才会调度到这台机器。
down 手动停用某台机器。

这其实就是一些健康检查参数,但是这些参数存在不足,在实际应用中,可以结合 keepalived 来完成,后面会单独说明。 

 

server 段关于反向代理的一些配置:

参数 说明
proxy_redirect 重写应答头部的报文
proxy_connect_timeout nginx 将一个请求发送至 upstream server 之前等待的最大时长
proxy_set_header 将发送至 upsream server 的报文的某首部进行重写
proxy_cookie_domain 将 upstream server 通过 Set-Cookie 首部设定的 domain 修改为指定的值,可以为字符串、正则或变量
proxy_cookie_path 将 upstream server 通过 Set-Cookie 首部设定的 path 修改为指定的值,可以为字符串、正则或变量
proxy_hide_header 设定发送给客户端的报文中需要隐藏的首部
proxy_send_timeout 发送至 upstream server 的写操作的超时时长
proxy_read_timeout 发送至 upstream server 的读操作的超时时长
proxy_pass 指定将请求代理至 upstream server 的 URL 路径

其实上面的配置我们可以简单的做个调整就能变成我们反向代理的配置模板。

 

 

小结

 

简单的 TCP / 正向 / 反向代理负载均衡就这些内容,当然还要优化的空间,后面会专门针对 nginx 配置优化再度进行说明。

Guess you like

Origin www.cnblogs.com/Dy1an/p/11246021.html