• openresty proxy sse 服务


    实际上如果单纯的进行nginx sse 处理很简单,但是我们实际的场景存在数据访问控制以及数据处理
    对于此问题,我们可以使用sse client 包装,然后同时将我们的请求endpoint 暴露为一个sse 服务

    参考处理图

    代码说明

    • sse 服务
      基于nodejs 开发的一个测试,基于express
     
    const express = require('express');
    const  { sseMiddleware } = require('express-sse-middleware');
    const app = express()
    app.use(sseMiddleware);
    app.get('/sse', (req, res) => {
      const sse = res.sse(); // `adding Response.sse()` funciton
      let count = 0;
      setInterval(() => {
        sse.send(String(count++));
      }, 1000);
    });
     
     
    app.get('/ssev2', (req, res) => {
      res.writeHead(200,{
        'Content-Type':'text/event-stream'
      });
      setInterval(() => {
        res.write(`event:xxxx\ndata:${new Date().toLocaleTimeString()}\n\n`)
      }, 1000);
    });
     
    app.listen(3000);
    • nginx 处理
      基于openresty 包含了一个token处理以及基于sse client 获取sse 服务的数据
      nginx.conf
     
    user root; 
    master_process off;
    worker_processes 1;
    events {
        worker_connections  1024;
    }
    http {
        include       mime.types;
        default_type  text/html;
        lua_code_cache off;
        lua_package_path '/opt/lua/?.lua;;';
        real_ip_header     X-Forwarded-For;
        resolver 127.0.0.11;
        server {
           listen 80;
           charset utf-8;
           proxy_set_header X-Forwarded-For $remote_addr;
         proxy_buffering off;
         proxy_cache off;
           proxy_set_header Connection '';
         proxy_http_version 1.1;
         chunked_transfer_encoding off;
           default_type text/html;
           location /ssev2 {
               # 代理标准请求
               proxy_pass http://sse:3000;
           }
           location / {
             default_type text/event-stream;
             # 访问控制
             access_by_lua_block {
                local token, err = ngx.req.get_headers()["token"]
                if token == nil then
                    ngx.exit(ngx.HTTP_FORBIDDEN)
                end
             }
             // 内容处理,基于了sse client 
             content_by_lua_block {
                local sse = require "resty.sse"
                local cjson = require "cjson"
                local conn, err = sse.new()
                if not conn then
                    ngx.say("failed to get connection: ", err)
                end
                local res, err = conn:request_uri("http://sse:3000/ssev2")
                if not res then
                    ngx.say("failed to request: ", err)
                    return
                end
                while true
                 do 
                    local event, err = conn:receive()
                    if err then 
                        ngx.say(err) 
                    end
                    if event then  
                        ngx.say(cjson.encode(event)) 
                    end
                    ngx.flush(true)
                end
             }
            }
        }
    }

    运行

    nodejs 基于了ncc,整体基于docker-compose
    openresty

     
    FROM openresty/openresty:1.21.4.1-0-alpine-fat
    RUN apk add --no-cache git &&  /usr/local/openresty/luajit/bin/luarocks install lua-resty-sse

    node

    FROM node:14.19.3-slim
    COPY app/index.js /app/index.js
    CMD [ "node","/app/index.js" ]

    docker-compose

    version: '3'
    services:
      sse:
        build: 
         context: ./
         dockerfile: Dockerfile-node
        ports:
          - 3000:3000
      app:
        build: ./
        ports:
          - "80:80"
        volumes:
          - "./app/:/opt/app"
          - "./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf"

    运行效果

    • 默认

    • 包含token的

    说明

    以上是一个简单的测试,可以参考使用

    参考资料

    https://github.com/openresty/lua-nginx-module
    https://github.com/wojons/lua-resty-sse
    https://github.com/rongfengliang/openresty-sse-proxy

  • 相关阅读:
    深入浅出RxJava
    android 图像处理系列合集
    WebView·开发指南
    LocalBroadcastManager 的实现原理,Handler还是 Binder?
    TCP协议中的三次握手和四次挥手(图解)
    Android进程保活
    Android只能动态注册的广播Action
    WakeLock, AlarmManager, JobScheduler
    jQuery验证控件jquery.validate.js使用说明+中文API
    IntelliJ IDEA的自动提示貌似是区分大小写的,首字母小写的话,怎么都提示不出来。
  • 原文地址:https://www.cnblogs.com/rongfengliang/p/16328951.html
Copyright © 2020-2023  润新知