命令记不住

登陆

Nginx 负载均衡

Nginx负载均衡

1.负载均衡类型

1.Nginx负载均衡按层划分

负载均衡按层划分应用场景: 四层负载均衡
负载均衡按层划分应用场景: 七层负载均衡, Nginx最常用

Nginx负载均衡配置场景

Nginx实现负载均衡需要用到proxy_pass代理模块配置.

Nginx负载均衡是将客户端请求代理转发至一组upstream虚拟服务池

nginx 用yum源安装的,stream模块也用yum源安装

yum install -y nginx-mod-stream

安装所有模块

yum install -y nginx-all-modules

.

2.负载均衡反向代理优化

1.Nginx代理配置语法

Syntax: proxy_pass URL;
Default:    —
Context:    location, if in location, limit_except

http://localhost:8000/uri/
http://192.168.56.11:8000/uri/
http://unix:/tmp/backend.socket:/uri/

2.url跳转修改返回Location[不常用]参考URL

Syntax: proxy_redirect default;
proxy_redirect off;proxy_redirect redirect replacement;
Default:    proxy_redirect default;
Context:    http, server, location

3.添加发往后端服务器的请求头信息

Syntax: proxy_set_header field value;
Default:    proxy_set_header Host $proxy_host;
            proxy_set_header Connection close;
Context:    http, server, location

# 用户请求的时候HOST的值是www.bgx.com, 那么代理服务会像后端传递请求的还是www.bgx.com
proxy_set_header Host $http_host;
# 将$remote_addr的值放进变量X-Real-IP中,$remote_addr的值为客户端的ip
proxy_set_header X-Real-IP $remote_addr;
# 客户端通过代理服务访问后端服务, 后端服务通过该变量会记录真实客户端地址
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

4.代理到后端的TCP连接、响应、返回等超时时间, 如图

//nginx代理与后端服务器连接超时时间(代理连接超时)
Syntax: proxy_connect_timeout time;
Default: proxy_connect_timeout 60s;
Context: http, server, location

//nginx代理等待后端服务器的响应时间
Syntax: proxy_read_timeout time;
Default:    proxy_read_timeout 60s;
Context:    http, server, location

//后端服务器数据回传给nginx代理超时时间
Syntax: proxy_send_timeout time;
Default: proxy_send_timeout 60s;
Context: http, server, location

5.proxy_buffer代理缓冲区, 如图

//nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端,边收边传, 不是全部接收完再传给客户端
Syntax: proxy_buffering on | off;
Default: proxy_buffering on;
Context: http, server, location

//设置nginx代理保存用户头信息的缓冲区大小
Syntax: proxy_buffer_size size;
Default: proxy_buffer_size 4k|8k;
Context: http, server, location

//proxy_buffers 缓冲区
Syntax: proxy_buffers number size;
Default: proxy_buffers 8 4k|8k;
Context: http, server, location

6.Proxy代理网站常用优化配置如下,将配置写入新文件,调用时使用include引用即可

[root@Nginx ~]# vim /etc/nginx/proxy_params
proxy_set_header Host $http_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 60;
proxy_read_timeout 60;

proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;

7.代理配置location时调用, 方便后续多个Location重复使用

location / {
    proxy_pass http://127.0.0.1:8080;
    include proxy_params;
}

.

3.负载均衡相关参数配置

轮询
# 按时间顺序逐一分配到不同的后端服务器(默认)
weight
# 加权轮询,weight值越大,分配到的访问几率越高
ip_hash
# 每个请求按访问IP的hash结果分配,这样来自同一IP的固定访问一个后端服务器
url_hash
# 按照访问URL的hash结果来分配请求,是每个URL定向到同一个后端服务器
least_conn
# 最少链接数,那个机器链接数少就分发

1.Nginx负载均衡[wrr]轮询具体配置

upstream load_pass {
 server 10.0.0.7:80;
 server 10.0.0.8:80;
}

2.Nginx负载均衡[weight]权重轮询具体配置

upstream load_pass {
 server 10.0.0.7:80 weight=5;
 server 10.0.0.8:80;
}

3.Nginx负载均衡ip_hash具体配置, 不能和weight一起使用。

//如果客户端都走相同代理, 会导致某一台服务器连接过多
upstream load_pass {
 ip_hash;
 server 10.0.0.7:80 weight=5;
 server 10.0.0.8:80;
}

后端Web服务器在前端Nginx负载均衡调度中的状态

down  
# 当前的server暂时不参与负载均衡
backup  
# 预留的备份服务器
max_fails 
# 允许请求失败的次数
fail_timeout  
# 经过max_fails失败后, 服务暂停时间
max_conns 
# 限制最大的接收连接数

1.测试down状态, 测试该Server不参与负载均衡的调度

upstream load_pass {
 //不参与任何调度, 一般用于停机维护
 server 10.0.0.7:80 down;
}

2.测试backup以及down状态

upstream load_pass {
 server 10.0.0.7:80 down;
 server 10.0.0.8:80 backup;
 server 10.0.0.9:80 max_fails=1 fail_timeout=10s;
}

location  / {
 proxy_pass http://load_pass;
 include proxy_params;
}

3.测试max_fails失败次数和fail_timeout多少时间内失败多少次则标记down

upstream load_pass {
 server 10.0.0.7:80;
 server 10.0.0.8:80 max_fails=2 fail_timeout=10s;
}

4.测试max_conns最大TCP连接数

upstream load_pass {
 server 10.0.0.7:80;
 server 10.0.0.8:80 max_conns=1;
}

.

4.七层负载均衡

Nginx upstream虚拟配置语法

Syntax: upstream name { ... }
Default: -
Context: http

//upstream例子
upstream backend {
 server backend1.example.com       weight=5;
 server backend2.example.com:8080;
 server unix:/tmp/backend3;
 server backup1.example.com:8080   backup;
}
server {
 location / {
     proxy_pass http://backend;
 }
}

3.配置文件1

# 定义后端资源池
upstream proxy {
 server 172.16.1.7:80 max_fails=2 fail_timeout=10s;
 server 172.16.1.8:80 max_fails=2 fail_timeout=10s;
}
# https配置
server {
     listen       443 ssl;
     server_name  opxdev.com;

     ssl_certificate   /etc/nginx/ssl_key/server.crt;
     ssl_certificate_key  /etc/nginx/ssl_key/server.key;
     ssl_session_timeout 5m;
     ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
     ssl_prefer_server_ciphers on;

     location /{
             proxy_pass https://proxy;
             proxy_set_header  Host $host:$server_port;
             proxy_set_header  X-Real-IP  $remote_addr;
             proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
             client_max_body_size  100m;
     }

     error_log /var/log/proxy.log;

     error_page 404 /404.html;
     location = /404.html {
             root   /usr/share/nginx/html;
     }

     error_page 500 502 503 504 /50x.html;
     location = /50x.html {
             root   /usr/share/nginx/html;
     }

     location ~ /\.ht {
             deny  all;
     }
}
# 用户http请求跳转至https
server {
 listen 80;
 server_name opxdev.com;
 return 302 https://$server_name$request_uri;
}

4.配置文件2

upstream site {
    server 81.70.158.62:8180;
}
server {
    listen  80;
    server_name www.opsxdev.com;

    rewrite ^(.*)$  https://$host$1 permanent;
}
server {
    listen  80;
    server_name opsxdev.com;

    rewrite ^(.*)$  https://www.opsxdev.com$1 permanent;
}
server {
        listen       443 ssl;
        server_name  opsxdev.com;

  ssl_certificate   /etc/nginx/ssl_key/6098420_www.opsxdev.com.pem;
  ssl_certificate_key  /etc/nginx/ssl_key/6098420_www.opsxdev.com.key;
        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        rewrite ^/(?!theme|console|admin|api|init) /blogs/opsxdev$uri break;

      location /{
          proxy_pass http://site/;
          proxy_set_header  Host $host:$server_port;
          proxy_set_header  X-Real-IP  $remote_addr;
              proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          client_max_body_size  10m;
      }

        error_log /var/log/proxy.log;

        error_page 404 /404.html;
        location = /404.html {
                root   /usr/share/nginx/html;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
                root   /usr/share/nginx/html;
        }

        location ~ /\.ht {
                deny  all;
        }
}

5.优化,调用时使用include引用

server {
    listen 80;
    server_name nginx.oldboy.com;

    location / {
        proxy_pass http://172.16.1.7:8080;
        include proxy_params;
    }
}

# vim /etc/nginx/proxy_params
proxy_set_header Host $http_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 60;
proxy_read_timeout 60;

proxy_buffering on;
proxy_buffer_size 32k;
proxy_buffers 4 128k;

方便后续多个Location重复使用

5.四层负载均衡

Nginx负载均衡TCP实践
  • 配置Nginx4层负载均衡实现如下需求
    • 1.通过访问负载均衡的5555端口,实际是后端的web01的22端口在提供服务。
    • 2.通过访问负载均衡的6666端口,实际是后端的mysql的3306端口在提供服务。
1.需要用到 proxy_pass 代理模块配置

nginx 用 yum 源安装的,stream 模块也用 yum 源安装

yum install -y nginx-mod-stream

安装所有模块

yum install -y nginx-all-modules
2.Nginx四层负载均衡配置语法
stream {
    upstream backend {
        hash $remote_addr consistent;
        server backend1.example.com:12345 weight=5;
        server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
        server unix:/tmp/backend3;
    }
    server {
        listen 12345;
        proxy_connect_timeout 1s;
        proxy_timeout 3s;
        proxy_pass backend;
    }
}
3.线上四层代理示例

主配置文件,nginx.conf 开启 stream 模块

worker_processes  1;
  load_module lib64/nginx/modules/ngx_stream_module.so;
events {
    worker_connections  1024;
    use epoll;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
    }
    sendfile        on;
    keepalive_timeout  65;
    include conf.d/*.conf;
    server {
        listen       80;
        server_name  localhost;
        location / {
            root   /srv/www/htdocs/;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }
    }

    include vhosts.d/*.conf;
}
stream {
    log_format proxy '$remote_addr [$time_local] '
                 '$protocol $status $bytes_sent $bytes_received '
                 '$session_time "$upstream_addr" '
                 '"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
    access_log /var/log/nginx/tcp-access.log proxy ;
    open_log_file_cache off;
    include /etc/nginx/conf.d/*.stream;
}

子配置文件配置,xxxx.stream 配置反向代理

[admin@OPS /etc/nginx/conf.d] SUSE云端服务器
$cat hotwooolsession.stream
# 添加socket转发的代理
upstream session_proxy {
    hash $remote_addr consistent;
    # 转发的目的地址和端口
    server 192.168.49.2:32713 weight=5 max_fails=3 fail_timeout=60s;
}

# 提供转发的服务,即访问localhost:9001,会跳转至代理socket_proxy指定的转发地址
server {
    listen 20013;
    proxy_connect_timeout 3s;
    proxy_timeout 30s;
    proxy_pass session_proxy;
}

[admin@OPS /etc/nginx/conf.d] SUSE云端服务器
$cat hotwooolgateway.stream
# 添加socket转发的代理
upstream gateway_proxy {
    hash $remote_addr consistent;
    # 转发的目的地址和端口
    server 192.168.49.2:31742 weight=5 max_fails=3 fail_timeout=60s;
}

# 提供转发的服务,即访问localhost:9001,会跳转至代理socket_proxy指定的转发地址
server {
    listen 20021;
    proxy_connect_timeout 3s;
    proxy_timeout 30s;
    proxy_pass gateway_proxy;
}
4.Nginx四层负载均衡实战
[root@lb01 ~]# mkdir -p /etc/nginx/conf.c
[root@lb01 ~]# vim /etc/nginx/nginx.conf
# 在events层下面,http层上面配置include
include  /etc/nginx/conf.c/*.conf;

# 编写四层代理配置
[root@lb01 ~]# cd /etc/nginx/conf.c/
[root@lb01 conf.c]# cat stream.conf 
stream {
    #1.定义虚拟资源池
    upstream ssh {
        server 172.16.1.7:22;
    }

    upstream mysql {
        server 172.16.1.51:3306;
    }
    #2.调用虚拟资源池
    server {
        listen 5555;
        proxy_connect_timeout 1s;
        proxy_timeout 300s;
        proxy_pass ssh;
    }
    server {
        listen 6666;
        proxy_connect_timeout 1s;
        proxy_timeout 300s;
        proxy_pass mysql;
    }
}
[root@lb01 conf.c]# systemctl restart nginx

.

6.动静分离

动静分离, 通过中间件将动态请求和静态请求进行分离, 分离资源, 减少不必要的请求消耗, 减少请求延时。
好处: 动静分离后, 即使动态服务不可用, 但静态资源不会受到影响

通过中间件将动态请求和静态请求分离

Nginx动静分离应用案例

0.环境准备

系统 服务 服务 地址
CentOS7.5 负载均衡 Nginx Proxy 10.0.0.5
CentOS7.5 静态资源 Nginx Static 10.0.0.7
CentOS7.5 动态资源 Tomcat Server 10.0.0.8

1.在10.0.0.7服务器上配置静态资源

[root@web01 conf.d]# cat ds_oldboy.conf
server{
     listen 80;
     server_name ds.oldboy.com;
     root /soft/code;
     index index.html;

     location ~* .*\.(png|jpg|gif)$ {
             root /soft/code/images;
     }
}

# 准备目录, 以及静态相关图片
[root@web01 ~]# mkdir /soft/code/images -p
[root@web01 ~]# wget -O /soft/code/images/nginx.png http://nginx.org/nginx.png
[root@web01 ~]# systemctl restart nginx

2.在10.0.0.8服务器上配置动态资源

[root@web01 ~]# yum install -y tomcat
[root@web01 ~]# systemctl start tomcat
[root@web01 ~]# mkdir /usr/share/tomcat/webapps/ROOT
[root@web01 ~]# vim /usr/share/tomcat/webapps/ROOT/java_test.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<HTML>
 <HEAD>
     <TITLE>JSP Test Page</TITLE>
 </HEAD>
 <BODY>
   <%
     Random rand = new Random();
     out.println("<h1>Random number:</h1>");
     out.println(rand.nextInt(99)+100);
   %>
 </BODY>
</HTML>

3.在负载均衡10.0.0.5上配置调度, 实现访问jsp和png

root@lb01 conf.d]# cat ds_proxy.conf 
upstream static {
     server 10.0.0.7:80;
}
upstream java {
     server 10.0.0.8:8080;
}
server {
     listen 80;
     server_name ds.oldboy.com;
     location / {
             root /soft/code;
             index index.html;
     }
     location ~ .*\.(png|jpg|gif)$ {
             proxy_pass http://static;
             include proxy_params;
     }
     location  ~ .*\.jsp$ {
             proxy_pass http://java;
             include proxy_params;
     }
}
[root@lb01 conf.d]# systemctl restart nginx

4.通过负载测试访问静态资源
5.在负载均衡10.0.0.5上整合动态和静态资源的html文件

[root@lb01 ~]# mkdir /soft/code -p
[root@lb01 ~]# cat /soft/code/index.html
<html lang="en">
<head>
     <meta charset="UTF-8" />
     <title>测试ajax和跨域访问</title>
     <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></script>
</head>
<script type="text/javascript">
$(document).ready(function(){
     $.ajax({
     type: "GET",
     url: "http://ds.oldboy.com/java_test.jsp",
     success: function(data) {
             $("#get_data").html(data)
     },
     error: function() {
             alert("fail!!,请刷新再试!");
     }
     });
});
</script>
     <body>
             <h1>测试动静分离</h1>
             <img src="http://ds.oldboy.com/nginx.png">
             <div id="get_data"></div>
     </body>
</html>

6.测试动态和静态资源是否能正常加载在一个html文件中
7.当使用systemctl stop nginx停止Nginx后, 会发现静态内容无法访问, 动态内容依旧运行正常
8.当使用systemctl stop tomcat停止tomcat后, 静态内容依旧能正常访问, 动态内容将不会被请求到

7.Nginx通过来源设备拆分访问页面

2.根据不同的浏览器, 以及不同的手机, 访问的效果都将不一样。

//通过浏览器来分别连接不同的浏览器访问不同的效果。
http {
...
 upstream firefox {
     server 172.31.57.133:80;
 }
 upstream chrome {
     server 172.31.57.133:8080;
 }
 upstream iphone {
     server 172.31.57.134:8080;
 }
 upstream android {
     server 172.31.57.134:8081;
 }
 upstream default {
     server 172.31.57.134:80;
 }
...
}

//server根据判断来访问不同的页面
server {
 listen       80;
 server_name  www.xuliangwei.com;

 #safari浏览器访问的效果
 location / {
     if ($http_user_agent ~* "Safari"){
     proxy_pass http://dynamic_pools;
     }   
 #firefox浏览器访问效果
     if ($http_user_agent ~* "Firefox"){
     proxy_pass http://static_pools;
     }
 #chrome浏览器访问效果
     if ($http_user_agent ~* "Chrome"){
     proxy_pass http://chrome;
     } 

 #iphone手机访问效果
     if ($http_user_agent ~* "iphone"){
     proxy_pass http://iphone;
     }

 #android手机访问效果
     if ($http_user_agent ~* "android"){
     proxy_pass http://and;
     }

 #其他浏览器访问默认规则
     proxy_pass http://dynamic_pools;
     include proxy.conf;
     }
 }
}

3.根据访问不同目录, 代理不同的服务器

//默认动态,静态直接找设置的static,上传找upload
 upstream static_pools {
     server 10.0.0.9:80  weight=1;
 }
upstream upload_pools {
      server 10.0.0.10:80  weight=1;
 }
upstream default_pools {
      server 10.0.0.9:8080  weight=1;
}

 server {
     listen       80;
     server_name  www.xuliangwei.com;

#url: http://www.xuliangwei.com/
 location / { 
     proxy_pass http://default_pools;
     include proxy.conf;
 }

#url: http://www.xuliangwei.com/static/
 location /static/ {
     proxy_pass http://static_pools;
     include proxy.conf;
 }

#url: http://www.xuliangwei.com/upload/
 location /upload/ {
     proxy_pass http://upload_pools;
     include proxy.conf;
 }
}

//方案2:以if语句实现。
if ($request_uri   ~*   "^/static/(.*)$")
{
     proxy_pass http://static_pools/$1;
}
if ($request_uri   ~*   "^/upload/(.*)$")
{
     proxy_pass http://upload_pools/$1;
}
location / { 
 proxy_pass http://default_pools;
 include proxy.conf;
}

.

1

1

推荐阅读