Hello,

I'm trying to write a simple function with OpenResty, Redis and RabbitMQ. The use case is the following, we receive requests on /data?ip=x.x.x.x, and the parameter ip needs to be lookep up in a Redis database. If we find a value, we return it, otherwise, we send the ip to a RabbitMQ exchange to be analyzed and saved in Redis by another app.

I have one performance constraint, this endpoint needs to reply within 8 to 10ms with thousands of calls every second.

I've written a first version which complies with the business requirements, but not yet with the performance.

It seems that the RabbitMQ publishing part is bringing the performance down by a 10x factor.
If I only keep the Redis read, I get an average response time of 1-2ms, with the RabbitMQ publish, I'm up to 15ms and huge standard deviation.

What should I try in order to improve this ?

worker_processes auto;
error_log error.log;
events {
    worker_connections 1024;
}
http {
    server {
        listen 8080;
        location /data {
            default_type text/html;

            content_by_lua_block {
                local redis = require "resty.redis"
                local red = redis:new()

                local strlen =  string.len
                local cjson = require "cjson"
                local rabbitmq = require "resty.rabbitmqstomp"

                -- connect via ip address directly
                local ok, err = red:connect("127.0.0.1", 6379)

                if not ok then
                    ngx.say("failed to connect: ", err)
                    return
                end

                local ip = ngx.var.arg_ip

                local res, err = red:get(ip)
                if not res then
                    ngx.say("failed to get ip: ", err)
                    return
                end

                local ok, err = red:set_keepalive(10000, 100)
                if not ok then
                    ngx.say("failed to set keepalive: ", err)
                    return
                end

                if res == ngx.null then
                    ngx.say("\n")

                    local opts = { username = "guest",
                                    password = "guest",
                                    vhost = "/" }

                    local mq, err = rabbitmq:new(opts)

                    if not mq then
                        return
                    end

                    local ok, err = mq:connect("127.0.0.1",61613) 

                    if not ok then
                        return
                    end

                    local msg = {ip=ngx.var.arg_ip}
                    local headers = {}
                    headers["destination"] = "/exchange/xandr"
                    headers["persistent"] = "true"
                    headers["content-type"] = "text/plain"

                    local ok, err = mq:send(ngx.var.arg_ip, headers)
                    if not ok then
                        return
                    end

                    local ok, err = mq:set_keepalive(10000, 100)
                    if not ok then
                        return
                    end

                    return
                end

                ngx.say(res)
            }
        }
    }
}
    18 days later
    Write a Reply...