Traceless

使用Nginx完成微信小程序多域名多Web\Websocket反代
背景 最近在进行微信小程序的服务端开发,后台采用websocket提供通讯、Webapi提供数据读取及提交、使...
扫描右侧二维码阅读全文
04
2018/08

使用Nginx完成微信小程序多域名多Web\Websocket反代

背景

最近在进行微信小程序的服务端开发,后台采用websocket提供通讯、Webapi提供数据读取及提交、使用阿里云CDN进行静态资源存储。这些!都!不!是!重!点!

然而

重点是,测试服务器(一台WIN ECS),负载2个WEBPAI(有一个是以前的项目测试的)、两个Websocket服务器。而且微信小程序的后台ws及http都要求进行证书加密为wss和https,并且都需要所有端口为443默认端口。

怎么办?

很明显,IIS(Win server2008\iis 7.0)可以通过直接修改IIS配置文件的方式进行HTTPS站点通过不同域名共用443端口,但Websocket无法托管在iis 7.0上(据说iis 8.5开始可以了)

抄家伙!

具体的项目技术架构我就不描述了,这里主要记录Nginx如何将若干Web(https)、Websocket(wws)利用反代和不同域名共用443端口,下面是四个大爷

大爷 大爷结构
webapi1 使用asp.net web api +swagger,其中有redis、drapper
webapi2 同上
websocket1 使用supersocket框架,其中使用到redis,以winservice形式运行
websocket2 同上

干!

流程

部署Web到服务器IIS

部署两个webapi网站至iis[自行百度],并绑定https端口为444、445(你可以用其他端口,只要不是443就行)

注意在Web.config中按照自己的要求添加跨域
普通Nerframework版本,在System.webServer节点下添加.

<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Request-Headers" value="*" />
<add name="Access-Control-Request-Method" value="*" />
<add name="Access-Control-Allow-Methods" value="*" />
</customHeaders>
</httpProtocol>

Netcore版本需要引用Microsoft.AspNetCore.Mvc.Cors(如果没有的话,去Nuget搜索并引用)
然后在ConfigureServices部分配置如下:

public void ConfigureServices(IServiceCollection services)
{
//配置跨域处理
services.AddCors(options =>
{
options.AddPolicy("any", builder =>
{
builder.AllowAnyOrigin() //允许任何来源的主机访问
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();//指定处理cookie
});
});
}

然后在action或controller上使用标签 [EnableCors("any")]
进行约束.

以winservice方式发布websocket至服务器(当然其他能够运行websocket的方式都可以)

调试技巧
winservice调试和运行可以使用topself进行,然而,我并没有使用!
那么,如何本机调试呢?
我们使用一个神奇的方法,Debugger.Launch();
该方法会触发会自动弹出VS Debug的附加进程调试框,并选择附加到VS进行附加调试,当然也可以选择跳过不附加,为了在Release版本中不弹窗,可以使用条件编译.

 protected override void OnStart(string[] args)
        {
        #if DEBUG //只有在Debug版本才会触发,release版本会跳过其中内容
            Debugger.Launch();
        #endif
            if (!bootstrap.Initialize())
            {
                throw new Exception("创建失败!");
                return;
            }

            var result = bootstrap.Start();

            Console.WriteLine("Start result: {0}!", result);

            if (result == StartResult.Failed)
            {
                throw new Exception("启动失败!");
                return;
            }
        }

Nginx反代所有项目端口到443并使用证书加密

测试websocket及webApi畅通以后,来到了Nginx环节,
首先准备好若干域名并解析到服务器Ip(可以一个大爷一个域名,也可以都是用一个域名然后使用a.webapi.com/path/的形式进行反代)为了同时演示两种方式

我们这里使用
a.webapi.com
b.webapi.com
wss.com
(websocket使用wss.com/wssa及wss.com/wssb进行反代,端口分别为2012 2013)

  1. 下载并安装Nginx 不提了
  2. 配置Ngnix

打开Ngnix目录下的配置文件nginx.cof
编辑如下:


#user  nobody;
worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

events {
    worker_connections  4096;#自己根据需求改
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       8080;#nginx的访问端口,随意
        server_name  localhost;#nginx的访问地址域名,可以填写自己的域名也可以直接localhost

        location / {
            root   html;
            index  index.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
server_names_hash_bucket_size 64;
include wss.conf;# 这里我们将反向代理新建一个文件引入进来
    client_max_body_size 3m;# 上传大小单位M 微信小程序上传大图片时可能需要设置
}

同目录新建wss.conf

# wss配置
server {
    listen 443 ssl;#默认https和wss协议端口
    server_name wss.com
    ssl_certificate /wss.com/Nginx/1_wss.com_bundle.crt;#你的上传到服务器的证书位置
    ssl_certificate_key /wss.com/Nginx/2_wss.com.key;#你的上传到服务器的证书位置
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;
    #wss协议转发 小程序里面要访问的链接
    location / wssa {#此处配置urlpath
        proxy_pass http://127.0.0.1:2012/;#Websocket本机地址和端口
        proxy_http_version 1.1;
        proxy_connect_timeout 4s; #配置点1
        proxy_read_timeout 3000s; #配置点2,防止websocket长连接被关闭,根据需求调整
        proxy_send_timeout 12s; #配置点3
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }    
    location / wssb {#此处配置urlpath
        proxy_pass http://127.0.0.1:2013/;#Websocket本机地址和端口
        proxy_http_version 1.1;
        proxy_connect_timeout 4s; #配置点1
        proxy_read_timeout 3000s; #配置点2,防止websocket长连接被关闭,根据需求调整
        proxy_send_timeout 12s; #配置点3
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
    }    
}
#https配置
server {
    listen 443;#默认https和wss协议端口
    server_name a.webapi.com;
    ssl_certificate /a.webapi.com/Nginx/1_a.webapi.com_bundle.crt;#你的上传到服务器的证书位置
    ssl_certificate_key /a.webapi.com/Nginx/2_a.webapi.com.key;#你的上传到服务器的证书位置
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:50m;
    ssl_protocols SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    underscores_in_headers on;#开启自定义头信息的下划线
    #https协议转发 小程序里面要访问的链接
    location /{
    proxy_pass https://localhost:444/;#代理到原有的https的地址去
    #注意下面部分和wss不一样
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size    2000m;
    }
}

server {
    listen 443;#默认https和wss协议端口
    server_name b.webapi.com;
    ssl_certificate /b.webapi.com/Nginx/1_b.webapi.com_bundle.crt;#你的上传到服务器的证书位置
    ssl_certificate_key /b.webapi.com/Nginx/2_b.webapi.com.key;#你的上传到服务器的证书位置
    ssl_session_timeout 5m;
    ssl_session_cache shared:SSL:50m;
    ssl_protocols SSLv3 SSLv2 TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
    underscores_in_headers on;#开启自定义头信息的下划线
    #https协议转发 小程序里面要访问的链接
    location /{
    proxy_pass https://localhost:445/;#代理到原有的https的地址去
    #注意下面部分和wss不一样
    proxy_set_header Host $host:$server_port;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header REMOTE-HOST $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    client_max_body_size    2000m;
    }
}

这样,我们
访问https://a.webapi.com/
就可以直接被代理转到
https://localhost:444/

访问https://b.webapi.com/
就可以直接被代理转到
https://localhost:445/

连接wss://wss.com/wssa
可以连上服务器2012端口上的websocket,
wss://wss.com/wssb
可以连上服务器2013端口上的websocket(注意,服务器真实WEB是HTTPS已经加密的,而websocket没有加密,而是在反代的时候顺便加密为wss了)
四个项目对外呈现的接口均为443且经过证书加密,符合微信的要求。可发布了!

本文为流水账式记录文,主要是为了方便日后回忆。若您看到本文有些不明白和按照本文无法完成效果的情况,可以联系我。QQ415206409,加好友请备注来意~谢谢,最后,如果大佬看了本文解决了问题,不放点击下面的赞赏给我打钱!

当然!如果您有任何建议!和更牛逼的方法!请联系我!或者留言指导~感激不尽

最后修改:2018 年 10 月 10 日 02 : 26 PM
如果觉得我的文章对你有用,请随意赞赏

发表评论