• 回家
    2019-07-08
    问题一:将表格利用cjson进行序列化之后发送
    问题二:通过设置定时器,在不能使用cosocket的阶段使用

    作者回复: 第二个答案是对的。第一个确实是可以的,但并非最好的方案,send 函数不仅支持字符串,还支持 table,这也是隐藏的优化点。

     1
     1
  • wusiration
    2019-07-13
    问题一:将table通过cjson序列化,但是看到老师有说send函数支持table,查阅api文档有说The input argument data can either be a Lua string or a (nested) Lua table holding string fragments.In case of table arguments, this method will copy all the string elements piece by piece to the underlying Nginx socket send buffers, which is usually optimal than doing string concatenation operations on the Lua land.
    问题二:通过shared dict进行数据传递
    展开

    作者回复: 接收 table 而非字符串,是 OpenResty Lua API 的一个重要的优化点。
    通过shared dict进行数据传递,这个我不是很明白,这个是如何绕过限制的呢?

     1
    
  • 小超人
    2019-07-13
    有个真实需求:
    client --密文--> Openresty解密 --明文--> server
    client <--密文-- Openresty加密 <--明文-- server
    1. 这是TCP应用,send/recv不一定是一对儿,比如有个大请求,client需要send 10次以后再收;
    2. Openresty知道client发过来的密文格式,带total_len,可以正常receive(total_len)就可以了;
    3. 【问题】Openresty不知道业务数据格式,在receive上游服务器时,遇到两个问题:
    *3.1* 不知道什么时候receive,如1.描述,Openresty将明文转发至server时,server不一定有返回数据;
    *3.2*如果来了数据,不知道该收多少,因为不知道业务数据的格式。
    【我现在的做法是】
    1. Openresty receive server那一侧,设置了一个buf_len,和一个较小的超时,比如200ms;
    2. Openresty每转发一次数据到server,都尝试receive一下server,如果超时,不报错不返回;如果receive到数据了,就加密返回后再循环receive,直到无数据(超时);
    这样虽然解决了问题,但是性能太差了,在openresty---server那一侧,至少要receive超时一次,才能知道收完数据了。
    【请问】有更好的解决办法吗?
    展开

    作者回复: 我理解了你的问题,尝试回答下,不一定准确:
    1. client 会传上来 total_len,那么 OpenResty 就能计算出来第几次 send 是最后一次。在最后一次 client send 的数据解密并转发给上游 server 后,开始 receive server。是否可以解决呢?
    2. 这个有有些尴尬了,即使OpenResty 不关心数据格式,至少也要知道数据长度或者结束符,这两个的其中一个。不然无法知道何时结束。

     2
    
  • helloworld
    2019-07-12
    老师:
    [error] 16239#16239: *5 attempt to send data on a closed socket: u:0000000000000000, c:0000000000000000
    客户端每次post数据过来,lua都可以正确的将数据写入redis,但是error.log日志中总是报这个错误。
    老师,我没用到redis连接池,我这个应用场景是每隔一段时间post请求往redis写数据,所以没必要使用连接池。关于redis的语句只有下面这些:
    local redis = require "resty.redis"
    local red = redis:new()
    red:set_timemout(2000) -- 2 sec
    local ip = "127.0.0.1"
    local port = 6379
    local ok, err = red:connect(ip, port)
    if not ok then
        ...
    end
    ok, err = red:hset(data_time, client, json_encode(data))
    if not ok then
        ...
    end
    展开

    作者回复: 建议在 redis:new() 的时候判断下是否成功。
    另外附上 OpenResty 作者给这个错误的排查意见:https://github.com/openresty/lua-resty-redis/issues/27#issuecomment-28166754,自然是更加权威的。

     1
    
  • helloworld
    2019-07-08
    [error] 16239#16239: *5 attempt to send data on a closed socket: u:0000000000000000, c:0000000000000000
    客户端每次post数据过来,lua都可以正确的将数据写入redis,但是error.log日志中总是报这个错误,求解。

    作者回复: 是否使用了redis 的连接池?猜测连接池里面有不正常的连接,但是被复用了。可以确认下放进连接池之前,代码中是否判断了连接是否正常?

    
    
  • helloworld
    2019-07-08
    老师,是不是不论在哪个阶段运行ngx.say('hello'),都会在执行完本阶段剩余代码后直接响应给客户端,不会继续执行其他阶段了。我测试是这样的。

    作者回复: 并不是,你可以看下它的执行阶段的顺序图:https://github.com/moonbingbing/openresty-best-practices/blob/master/images/openresty_phases.png,你可以做这个测试,在 content 里面 ngx.say,然后在 log 或者 body filter 阶段打印下日志试试。

     1
    
  • 回家
    2019-07-08
    文中利用cosocket将TCP请求发送到www.baidu.com的例子,我运行了一下包含头域Host:www.baidu.com和不包含该头域的请求,抓包来看,也确实是一个包含Host头域,一个不包含,两个请求都能得到百度的200应答。有一个问题是,我在本地使用proxy,然后转upstream时,如果不指定请求头域为请求到的域名的话,就不能得到正确的应答。这里是我写的关于这个问题的博客链接:https://blog.csdn.net/u013139008/article/details/94732537 介绍这个问题。老师,你知道这里必须要指定头域是www.baidu.com的原因吗?

    作者回复:
    一般来说,一个 ip 上可能会运行多个网站,所以会通过 server name 来做区分,比如 Nginx 中的 server 这个指令。如果没有设置
     proxy_set_header Host "www.baidu.com";
    的话,在路由的时候就可能会找不到 server。

     1
    
  • helloworld
    2019-07-08
    👍
    
    
我们在线,来聊聊吧