You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by GitBox <gi...@apache.org> on 2021/07/26 11:39:15 UTC

[GitHub] [apisix] philzhangrui opened a new issue #4675: request help: Write your own plug-ins to improve performance

philzhangrui opened a new issue #4675:
URL: https://github.com/apache/apisix/issues/4675


   ### Issue description
   
   
   I wrote a plug-in myself. In the access phase, add 1 to the number of requests in redis, and then return the error code. Each execution takes more than 1 second. I want to know why
   
   
   
   local core = require("apisix.core")
   local plugin_name = "limit-conn-ext"
   local redis_new = require("resty.redis").new
   local ngx         = ngx
   local code
   
   local script = [=[
       if redis.call('ttl', KEYS[1]) < 0 then
           redis.call('set', KEYS[1], ARGV[1] - 1, 'EX', ARGV[2])
           return ARGV[1] - 1
       end
       return redis.call('incrby', KEYS[1], -1)
   ]=]
   
   
   local lrucache = core.lrucache.new({
       type = "plugin",
   })
   
   local schema = {
       type = "object",
       properties = {
           -- 请求通过数
           conn = {type = "integer", exclusiveMinimum = 0},
           --排队数
           burst = {type = "integer",  minimum = 0},
           --排队等待时间
           default_conn_delay = {type = "number", exclusiveMinimum = 0},
           key = {type = "string" },
           -- 超过排队返回码
           rejected_code = {
               type = "integer", minimum = 200, maximum = 599, default = 503
           },
           --单位时间
           time_window = {type = "integer",  exclusiveMinimum = 0},
           policy = { type = "string" }
       },
       required = {"conn", "burst", "default_conn_delay", "key"},
       dependencies = {
           policy = {
               oneOf = {
                   {
                       properties = {
                           policy = {
                               enum = {"redis"},
                           },
                           redis_host = {
                               type = "string", minLength = 2
                           },
                           redis_port = {
                               type = "integer", minimum = 1, default = 6379,
                           },
                           redis_password = {
                               type = "string", minLength = 0,
                           },
                           redis_database = {
                               type = "integer", minimum = 0, default = 0,
                           },
                           redis_timeout = {
                               type = "integer", minimum = 1, default = 1000,
                           },
                       },
                       required = {"redis_host"},
                   },
                   {
                       properties = {
                           policy = {
                               enum = {"redis-cluster"},
                           },
                           redis_cluster_nodes = {
                               type = "array",
                               minItems = 2,
                               items = {
                                   type = "string", minLength = 2, maxLength = 100
                               },
                           },
                           redis_password = {
                               type = "string", minLength = 0,
                           },
                           redis_timeout = {
                               type = "integer", minimum = 1, default = 1000,
                           },
                           redis_cluster_name = {
                               type = "string",
                           },
                       },
                       required = {"redis_cluster_nodes", "redis_cluster_name"},
                   }
               }
           }
       }
   }
   
   
   local _M = {
       version = 0.1,
       priority = 1004,
       name = plugin_name,
       schema = schema,
   }
   
   function _M.check_schema(conf)
       local ok, err = core.schema.check(schema, conf)
       if not ok then
           return false, err
       end
   
       return true
   end
   
   
   
   
   
   function _M.access(conf, ctx)
   
   
       local red = redis_new()
       local timeout = conf.redis_timeout or 1000    -- 1sec
   
       red:set_timeouts(timeout, timeout, timeout)
   
       local ok, err = red:connect(conf.redis_host, conf.redis_port or 6379)
       if not ok then
           return false, err
       end
   
       local count
       count, err = red:get_reused_times()
       if 0 == count then
           if conf.redis_password and conf.redis_password ~= '' then
               local ok, err = red:auth(conf.redis_password)
               if not ok then
                   return nil, err
               end
           end
   
           -- select db
           if conf.redis_database ~= 0 then
               local ok, err = red:select(conf.redis_database)
               if not ok then
                   return false, "failed to change redis db, err: " .. err
               end
           end
       elseif err then
           -- core.log.info(" err: ", err)
           return nil, err
       end
   
       local key = ctx.var["uri"]
       core.log.warn("limit key: ", key)
       core.log.warn("limit conn: ", conf.conn)
       core.log.warn("limit conf.time_window: ", conf.time_window)
   
       local remaining, err = red:eval(script, 1, key, conf.conn, conf.time_window)
       core.log.warn("remaining:",remaining)
       if err then
           return nil, err
       end
   
       if remaining < 0 or  remaining == 0 then
   
           local queueKey = key.."queue"
           --看队列长度是否已满,
           local queueSize =  red:llen(queueKey)
           core.log.warn("queueSize:",queueSize)
           if queueSize ==0 or queueSize <conf.burst then
               local value = key .."|"..ngx.now()*1000
               local  size,error = red:lpush(queueKey,value);
               core.log.warn("addQueueSize:",size)
               if not error then
                   --加入队列失败
                   code = 202;
               end
               --加入队列
               code = 203
           else
               -- 队列已满
               code = 201
           end
       else
           -- 直接通过
           code = 200
       end
   
       local ok, err = red:set_keepalive(10000, 100)
       if not ok then
           core.log.error("limit-conn-ext error",err)
           return nil, err
       end
   
   end
   
   
   
   function _M.body_filter(conf, ctx)
           ngx.arg[1] = code
           ngx.arg[2] = true
   end
   
   return _M
   
   
   ### Environment
   
   Request help without environment information will be ignored or closed.
   
   * apisix version (cmd: `apisix version`):
   * OS (cmd: `uname -a`):
   * OpenResty / Nginx version (cmd: `nginx -V` or `openresty -V`):
   * etcd version, if have (cmd: run `curl http://127.0.0.1:9090/v1/server_info` to get the info from server-info API):
   * apisix-dashboard version, if have:
   * luarocks version, if the issue is about installation (cmd: `luarocks --version`):
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [apisix] philzhangrui closed issue #4675: request help: Write your own plug-ins to improve performance

Posted by GitBox <gi...@apache.org>.
philzhangrui closed issue #4675:
URL: https://github.com/apache/apisix/issues/4675


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscribe@apisix.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org