Netty和Nginx强强联合

2,314 阅读3分钟

1632929158(1).jpg

前置知识:

我们需要知道Netty的Channel并不能进行序列化,所以不能采用例如Redis或者clone的方式进行存储,如果要存储起来也只能在JVM的内存里面进行存储,但同时我们的Netty的端口号也不能进行暴露出去,否则可能有被人攻击的危险,正常都是使用Nginx的ws路由进行反向代理的.

Netty的服务端如何操作

这是一个简单的Netty服务端搭建- 其中WebSocketServerProtocolHandler是帮助建立一个WebSocket链接且实现了心跳功能,但是需要自己进行Text的逻辑操作,其中有两个比较关键的参数是WebSocketPathMaxFramSize


WebSocketPath:(chat) 这个参数对于我有两个意义,一:是可以通过ws/wss的链接进行路径判断,如果该链接上有chat那么就会尝试进行websocket链接, 二:就是在Nginx上进行ws路由的时候 location所带的路由参数转发升级后,会将chat带过去,虽然ng没写 但是会在请求头里面携带过去,而WebSocketServerProtocolHandler的第一个参数或者是path也会根据这个进行路由操作


MaxFramSize:(1024x1024x3)这个参数是因为我需要Netty这个框架或者是WebSocket长连接传输大一点的文件,当我们传输的文本或者文件超过默认值的时候,那么服务端会关闭这个Channel ,然后客户端会报错说(你的主机已经中断一个已经存在的链接 接着报错不活跃)所以用到了这个参数


版本介绍:netty-all 4.1.63.Final (4.0.13.Final没有)
链接地址(非Nginx): wss://127.0.0.1:8081/chat

public class EchoServer {
    public  void  start (Integer port){
        NioEventLoopGroup boot = new NioEventLoopGroup();
        NioEventLoopGroup work = new NioEventLoopGroup();

        ServerBootstrap b = new ServerBootstrap();
         b.group(boot, work)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    protected void initChannel(SocketChannel s) throws Exception {
                        ChannelPipeline pipeline = s.pipeline();
                        pipeline.addLast("http-codec",new HttpServerCodec());//将请求和应答消息编码或者解码为HTTP消息
                        pipeline.addLast("aggergator",new HttpObjectAggregator(65536));//将HTTP消息的多个部分组成为u一个消息
                        pipeline.addLast("http-chunked",new ChunkedWriteHandler());//来向客户端发送HTML5文件 主要支持浏览器端和服务端进行通信
                        pipeline.addLast("websocket-handler",new WebSocketServerProtocolHandler("/chat",null,false,1024*1024*3));//
                        pipeline.addLast("my-handler",new MyHandler());//
                    }
                });
        try {
            Channel channel = b.bind(port).sync().channel();
            channel.closeFuture().sync();
            System.out.println("链接成功");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            boot.shutdownGracefully();
            work.shutdownGracefully();
        }
    }
    public static void main(String[] args) {
        EchoServer server = new EchoServer();
        server.start(8081);
    }
}

Nginx是如何配置的

原理其实就是做了http升级,然后进行的webSocket链接,此时我们配置完了链接地址之后就可以通过
链接地址:wss://127.0.0.1:8020/chat 进行webSocket长连接
好处:就是避免暴露真实的服务端,还可以在websocket处在做一些服务在均衡,平衡服务器之间的逻辑关系

map $http_upgrade $connection_upgrade {
      default upgrade;
      '' close;
   }
   upstream websocket {
      server 127.0.0.1:8081; #你的websocket地址
      keepalive 50;  #心跳
   }
   server {
      listen 8020;  #你的nginx监听的端口号 
      location /chat {  #这个是监听的端口并且路径上带这个参数的
         proxy_pass http://websocket;  #走到上面的websocket 
         proxy_http_version 1.1;  #升级http 变为1.1 在设置Upgrade Connection 就代表是长连接的意思了 
         proxy_set_header Upgrade $http_upgrade;  #这个变量在上面有配置
         proxy_set_header Connection $connection_upgrade;  #这个变量在上面有配置
      }
   }