pushpin openresty 集成试用

时间:2022-06-30 00:55:36

pushpin 是一个很不错的将restapi 转换为reailtime api 的proxy,openresty 具有很强的nginx 控制能力
可以方便的用来进行api 的开发,默认其他语言pushpin 提供了sdk ,但是lua 的暂时还没有,所以基于
http 请求,搞一个简单的测试,后期可以参考其他语言,封装为lua 模块

环境准备

  • docker-compose 文件
version: "3"
services:
  pushpin:
    image: fanout/pushpin
    environment:
    - "target=api:8080"
    - "LOGNAME=nobody"
    volumes:
    - "./routes:/etc/pushpin/routes"
    ports:
    - "5561:5561"
    - "5562:5562"
    - "5563:5563"
    - "7999:7999"
  api:
    build: ./
    ports:
    - "8080:8080"
    volumes:
    - "./nginx_lua/:/opt/app/"
    - "./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf"
  • openresty dockerfile
FROM openresty/openresty:alpine-fat
LABEL author="1141591465@qq.com"
RUN /usr/local/openresty/luajit/bin/luarocks install lua-resty-http
RUN opm get thibaultcha/lua-resty-jit-uuid
  • router 文件
    实际上官方提供的镜像对于router 基本是可选的,因为这个docker 镜像,默认参数太多。。。
  • nginx.conf
worker_processes 1;
user root;  
events {
    worker_connections 1024;
}
http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    lua_code_cache off;
    lua_need_request_body on;
    gzip on;
    resolver 127.0.0.11 ipv6=off;          
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
    lua_package_path '/opt/app/?.lua;;';
    server {
        listen 8080;
        server_name app;
        charset utf-8;
        default_type text/html;
        location / {
           default_type text/plain;
           index index.html index.htm;
        }
        location = /favicon.ico {
            root /opt/app/static;
        }
        location /userinfo {
            content_by_lua_block {
              require("api/userinfo")()
            }
        }
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root html;
        }

    }
}

lua publish 代码

代码比较简单,基于http 模块,同时注意content 内容需要一个\n 参数,这个稍有点坑,,,
ngx_lua/api/userinfo.lua

local json = require("cjson")
local http = require("resty.http")
function init()
    local uuid = require("resty.jit-uuid")
    uuid.seed()
    local method_name = ngx.req.get_method()
    if method_name == "GET" then
        ngx.header["Content-Type"] = "text/plain"
        ngx.header["Grip-Hold"] = "stream"
        ngx.header["Grip-Channel"] = "userinfo"
        ngx.say("is stream open")
        return
    end
    ngx.req.read_body()
    local body = ngx.req.get_body_data()
    if not body then
        if ngx.req.get_body_file() then
            return nil, "request body did not fit into client body buffer, consider raising 'client_body_buffer_size'"
        else
            return ""
        end
    end
    local mode = json.decode(body)
    local body_entity = {
        items = {
            {
                channel = mode.channel,
                -- id 必须唯一,为了方式使用了uuid lua 包
                id = uuid(),
                formats = {
                    ["http-stream"] = {
                     -- \n 很重要
                        content = json.encode(mode.data)..'\n',
                    },
                    -- action = "send"
                }
            }
        }
    }
    ngx.log(ngx.ERR, json.encode(body_entity))
    local requestapiurl = "http://pushpin:5561/publish/"
    local httpc = http.new()
    local res, err =
        httpc:request_uri(
        requestapiurl,
        {
            method = "POST",
            body = json.encode(body_entity),
            headers = {
                ["Content-Type"] = "application/json"
            }
        }
    )
    if not res then
        ngx.say("failed to request: ", err)
        return
    end
    ngx.log(ngx.ERR, res.body)
    ngx.say(res.body)
end
return init

启动&&测试

  • 启动
docker-compose up -d
  • 测试效果
    client (curl) stream 连接
curl http://localhost:7999/userinfo

发送消息,(openresty 端,而不是一般的pushpin 的rest 地址)

curl -X POST \
  http://localhost:8080/userinfo \
  -H 'Content-Type: application/json' \
  -H 'Postman-Token: a401a816-2f51-4183-811b-b62a5c9c66a3' \
  -H 'cache-control: no-cache' \
  -d '{
 "channel":"userinfo",
 "data":{
  "username":"demoapp\n,userinfo app \\n",
  "userage":333
 }
}'

内容
pushpin openresty 集成试用

说明

pushpin 支持的模型还是比较多的,不只是stream 还有websocket, sse。。。

参考资料

https://pushpin.org/docs/usage/#subscribing
https://github.com/rongfengliang/pushpin-openresty-docker-compose