nginx配置-多服务部署、负载均衡

目录

nginx代理多个服务器

多站点

多location

负载均衡配置

nginx代理socket.io服务

web前端

配置nginx.conf

socket.io服务器


 

nginx代理多个服务器

主要有两种方式

多站点

常用于在一台机器上部署多个不同站点, 各自有不同的域名,配置如下:

// nginx.conf
# nginx 80端口配置 (二级域名)
server {
    listen  80;
    server_name     abc.jd.com;
    location / {
        proxy_pass      http://localhost:8080; # 转发
    }
}

# nginx 80端口配置
server {
    listen  80;
    server_name     xyz.jd.com;
    location / {
        proxy_pass      http://localhost:8081;
    }
}

abc.jd.com将被自动代理到http://localhost:8080服务器上, 而xyz.jd.com则被自动代理到http://localhost:8081服务器上。

而对于那些只有一个域名,又不想申请多个域名的情况,可以选择下面的多location方式

 

多location

location是nginx配置文件中的一个配置项, 当需要在一个域名下面部署多个不同服务器,可使用该方案,配置如下:

location / {
    root   /html/;
    index  index.html index.html;
}
location /sig {
    root   /sig/;
    index  index.html index.html;
}

www.xxx.com 将会被导流到/html目录下

www.xxx.com/sig/ 将被导流到/sig目录下

在nginx中配置proxy_pass代理转发时,如果在proxy_pass后面的url加/,表示绝对根路径;如果没有/,表示相对路径,把匹配的

路径部分也给代理走。

下面列举四种情况分别用 http://192.168.2.1/proxy/b.html 进行访问。

location /proxy/ {
    proxy_pass http://127.0.0.1/;
}
代理到:http://127.0.0.1/b.html


location /proxy/ {
    proxy_pass http://127.0.0.1;
}
代理到:http://127.0.0.1/proxy/b.html


location /proxy/ {
    proxy_pass http://127.0.0.1/aaa/;
}
代理到:http://127.0.0.1/aaa/b.html


location /proxy/ {

    proxy_pass http://127.0.0.1/aaa;
}
代理到:http://127.0.0.1/aaab.html

 

负载均衡配置

nginx的负载均衡配置包含多个配置项,主要有backup,weight,down,max_fails,fail_timeout..  proxy_next_upstream,结合一个案例进行说明:


upstream S1{
ip_hash;
server 127.0.0.1:8501;
server 127.0.0.1:8502;
}

upstream S2{
server 127.0.0.1:8503;
server 127.0.0.1:8504;
fair;
}


upstream S3{
server 127.0.0.1:8505;
server 127.0.0.1:8506;
hash $request_uri;
hash_method crc32;
}


upstream server_A {

server 127.0.0.1:9000 weight=2 max_fails=3  fail_timeout=30s;
server 127.0.0.1:9001 weight=1 max_fails=3  fail_timeout=30s;
server 127.0.0.1:9002 weight=1  max_fails=3  fail_timeout=30s backup;

}


server {

    listen      443 ssl;

    include      /etc/nginx/ssl_certificate/ssl.conf;

    server_name test.xx.cn  ; 

  location / {

        # root /html;

        proxy_next_upstream  error | timeout | http_502 | http_503 | http_504 ;



        proxy_pass http://server_A/;

        proxy_buffer_size 64k;

        proxy_buffers  32 32k;

        proxy_busy_buffers_size 128k;

        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_read_timeout 120;

}



    location ~ ^/favicon\.ico$ {

        access_log off;

        deny all;

    }

    error_page  500 502 503 504  /50x.html;

        location = /50x.html {

        root  /usr/share/nginx/html;

    }

}

 

upstream:  server_A{}指定了三个服务器,其中9002端口服务器因为带有backup标识,作为备用服务器存在,也就是说当9001服务器正常时,9002服务器是不参与工作的,仅当9001服务器遇到了proxy_next_upstream指定的错误类型( error | timeout | http_502 | http_503 | http_504),nginx才会切换到备用服务器。

weight: 指定了服务器的权重, 其中9000服务器的流量将会是9001服务器的2倍。

max_fails:允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误

fail_timeout: 默认值10s,代表超时时间。

down: 表示当前的server暂时不参与负载

ip_hash:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session不能跨服务器的问题,如果后端服务器down掉,要手工down掉。

fair:(第三方插件)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。

url_hash:(第三方插件)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存服务器时比较有效。
在upstream中加入hash语句,hash_method是使用的hash算法。

proxy_pass: 指定要代理的服务器,当收到相应的location时,会导流到对应的服务器上。

proxy_next_upstream:

语法格式:
proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 |http_404 | off ...;

含义:
error:和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现错误 
timeout:和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现超时 
invalid_header:后端服务器返回空响应或者非法响应头 
http_500:后端服务器返回的响应状态码为500 
http_502:后端服务器返回的响应状态码为502 
http_503:后端服务器返回的响应状态码为503 
http_504:后端服务器返回的响应状态码为504 
http_404:后端服务器返回的响应状态码为404 
off:停止将请求发送给下一台后端服务器


默认值:
proxy_next_upstream error timeout;   

默认情况下, nginx只会捕获error,timeout这两种错误, nginx默认判断失败节点状态是并不以http错误状态来进行判断失败。

proxy_next_upstream使用场景: 当业务服务器返回500,502...错误时,将流量切换到备用服务器, 则可做如下配置:

proxy_next_upstream http_500 | http_502 | http_503 | http_504 |http_404;

proxy_next_upstream作用相当于是告知nginx来捕获相应的错误类型

proxy_next_upstream off
    关闭proxy_next_upstream.
    因为proxy_next_upstream 默认值: proxy_next_upstream error timeout;
场景:当访问server-A时,server-A返回error timeout时,访问会继续分配到下一台服务器处理,就等于一个请求分发到多台服务器,就可能出现多次处理的情况,如果涉及到充值,就有可能充值多次的情况,这种情况下就要把proxy_next_upstream关掉

 

nginx代理socket.io服务

我需要在一台服务器中部署多个服务, 包括网站,信令服务器等,且只有一个域名, 自然而然需要使用'多location'方式。在使用nginx代理socket.io信令服务器的时候,走了不少弯路,总结如下三个方面:

web前端

socket = io.connect('http://192.168.12.22');

socket.on(ping, function (data) {
console.log(data);
socket.emit('p','test');

弯路{

一开始我是希望在nginx配置文件中增加一个location:

location /proxy_sig/ {
...
}

我设想的是在web端通过 io.connect('http://192.168.12.22/proxy_sig/')来导流至该location,结果失败了。 查明原因,原来是io.connect()导致的, 无论我们使用何种域名, 经过socket.io转换后,到达nginx的请求url都变为:

http://192.168.12.22/socket.io/?EIO=3&transport=polling&t=Mwt30Fu

所以, 我们设想location proxy_sig是永远无法到达的, 于是,在nginx配置文件中增加location socket.io

location ~* \.io {
...
}

成功了.

}

 

配置nginx.conf

location ~* \.io {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
 
    proxy_pass http://localhost:3000;
    proxy_redirect off;
 
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
}

socket.io服务器

'use strict'

var log4js = require('log4js');
var http = require('http');
var https = require('https');
var fs = require('fs');
var socketIo = require('socket.io');
var express = require('express');
var serveIndex = require('serve-index');

log4js.configure({
    appenders: {
        file: {
            type: 'file',
            filename: 'app.log',
            layout: {
                type: 'pattern',
                pattern: '%r %p - %m',
            }
        }
    },
    categories: {
        default: {
            appenders: ['file'],
            level: 'debug'
        }
    }
});



var logger = log4js.getLogger();

var serverApp = express();

serverApp.use(serveIndex('./public'));
serverApp.use(express.static('./public'));


//var http_server = http.createServer(serverApp);
var http_server = http.createServer();
console.log(http_server);
var options = {
    key: fs.readFileSync('/luckzone_cert/key'),
    cert: fs.readFileSync('/luckzone_cert/pem')
};
var pepople_num = 0;

var https_server = https.createServer(options, serverApp);

var io = socketIo.listen(http_server);
http_server.listen(9001, '0.0.0.0');

function ioConnection(socket) {
    console.log('enter ioConnection');
    socket.on('message', (room, socketid, data) => {
        console.log('socket: recv message:', socket.id, socketid);
        // send message to the room , excpet myself.
        socket.to(room).emit('message', room, socketid, data);
    });

    socket.on('join', (room) => {
        socket.join(room);
        pepople_num = pepople_num + 1;
        console.log('socket: join', room);

        socket.emit('joined', room, socket.id);
        if (pepople_num > 1) {
            // there have other people in the room
            socket.to(room).emit('otherjoin', room, socket.id);
        }
    });

    socket.on('leave', (room) => {
        socket.to(room).emit('bye', room, socket.id);

        //send message to myself
        socket.emit('leaved', room, socket.id);
    });
}

function ioDisconnection(socket) {

}

io.sockets.on('connection', ioConnection);

https_server.listen(9002, '0.0.0.0');

需要注意的是, 我们是通过http服务,所以,一定要将socket.io和http服务绑定一起,从9001端口启动, nginx配置文件来处理前端请求和socket.io服务器之间的映射.

 

 

 

 

 

 

 

 

你可能感兴趣的:(nginx配置-多服务部署、负载均衡)