0

我在尝试完成这项工作时遇到了非常困难的时期,我有一个支持多个业务领域的微服务架构,现在我想添加一个新的微服务,它将公开一个套接字连接以提供一些实时信息给应用。检查下图:

应用架构

我将在这里分享一些方面,看看你是否可以帮助我解决这个配置问题。

我做了一些测试来确定问题出在哪里,我做了一个不使用 Nginx 和 ExpressGateway 直接连接到 Node API(在服务器上运行)的测试,检查下面的 Gif,一切都按预期工作:

看看它是如何工作的

它建立“轮询”连接,然后升级到我们想要的 Websocket,接收到消息而不建立任何新连接。

这是 API 服务器配置:

constructor() {
        this.app = express();
        this.initExpress();
        this.initExpressMiddleWare();
        this.dvConn = new DAO();
        this.server = this.start();
        this.io = io().attach(this.server, {
            path: `${config.BASE_PATH}`,
            origins: '*:*',
            transports:['polling', 'websocket'],
            serveClient: false
        });
        this.newSocketUsers = [];
        this.io.on('connection', (socket) => {
            console.log(`a user connected ${socket.id}`);
            const user_id = this.decode_id(socket.handshake.query.user_id).toString();
            const socket_id = socket.id;
            this.registerConnection(socket_id, user_id);
            socket.on('disconnect', () => {
                console.log(`a user disconnected ${socket.id}`);
                const socket_id = socket.id;
                this.unRegisteredConnection(socket_id);
            });
        });

这是一个 Angular 客户端应用程序的一部分来测试这个:

constructor(private http: HttpClient) {
    this.httpClient = http;
    this.socket = io('http://dev.server.com:3033', {
      query: {
        user_id: '988379518723645912'
      },
      transports: ['polling', 'websocket']
    });
    this.socket.on('reconnect_attempt', () => {
      this.socket.io.opts.transports = ['polling', 'websocket'];
    });
  }

  connect(): void {
    this.socket.on('connect', () => {
      console.log('Opening Connection');
    });
  }

现在问题来了,当它通过 Nginx 和 ExpressGateway 运行时,请参阅下面的 Gif 以了解应用程序如何首先记录 502 错误,并且它会继续轮询并且永远不会升级到 WebSocket,使得每发送一条新消息都会将其记录为新的投票请求:

看看它是如何不起作用的

我做了功课,我知道 Nginx 需要一些配置,这是我的 Nginx.conf 配置:

server {
        listen 443 ssl;
        client_max_body_size 12m;
        client_body_buffer_size 16k;
        server_name dv3.synth5.orcasnet.com api.orcasnet.com;
        ssl_certificate /etc/nginx/ssl/certificate.crt;
        ssl_certificate_key /etc/nginx/ssl/key.key;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers 'EECDH+AESGCM:EDH+AESGCMsssssss';
        location /  {
                proxy_temp_file_write_size 64k;
                proxy_connect_timeout 10080s;
                proxy_send_timeout 10080;
                proxy_read_timeout 10080;
                proxy_buffer_size 64k;
                proxy_buffers 16 32k;
                proxy_busy_buffers_size 64k;
                proxy_redirect off;
                proxy_request_buffering off;
                proxy_buffering off;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "upgrade";
                proxy_http_version 1.1;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $host;
                proxy_pass    http://gateway.domain.net:3020;
        }
}

最后是 ExpressGateway 策略配置:

socStg:
    apiEndpoints:
      - socStg
    policies:
      - cors:
      - log:
        - action:
            message: ${req.method} ${req.originalUrl} ${req.headers}
      - proxy:
          - action:
              serviceEndpoint: socStg
              changeOrigin: true
              ws: true
              timeout: 120000

我会很感激你能为我提供这个问题的任何帮助,在此先感谢。

4

2 回答 2

0

简单回答 Express-Gateway 不支持套接字连接,我需要直接使用 Nginx 部署 API。现在正在工作。

于 2020-05-14T13:10:34.973 回答
0

以下文档包含事件作为套接字..

https://www.express-gateway.io/docs/plugins/plugin-development/

module.exports = {
  version: '1.2.0',
  init: function (pluginContext) {
    pluginContext.eventBus.on('hot-reload', function ({ type, newConfig }) {
      // "type" is gateway or system
      // depends on what file was changed
      // newConfig - is newly loaded configuration of ExpressGateway
      console.log('hot-reload', type, newConfig);
    });

    pluginContext.eventBus.on('http-ready', function ({ httpServer }) {
      console.log('http server is ready', httpServer.address());

      // Proxy websockets to localhost:9015
      const httpProxy = require('http-proxy')
      var proxy = new httpProxy.createProxyServer({
        target: {
          host: 'localhost',
          port: 9015
        }
      });

      httpServer.on('upgrade', (req, socket, head) => {
        proxy.ws(req, socket, head);
      });
    });

    pluginContext.eventBus.on('https-ready', function ({ httpsServer }) {
      console.log('https server is ready', httpsServer.address());
    });

    pluginContext.eventBus.on('admin-ready', function ({ adminServer }) {
      console.log('admin server is ready', adminServer.address());
    });
  }
}
于 2020-06-24T02:14:21.897 回答