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/11/11 10:40:24 UTC

[GitHub] [apisix] shuaijinchao edited a comment on issue #4077: passive healthcheck not working after configuration changing

shuaijinchao edited a comment on issue #4077:
URL: https://github.com/apache/apisix/issues/4077#issuecomment-966193860


   > > @Ben0625 Could you try the `2.5` version? And test it whether it can be reproduced in `2.5`?
   > 
   > We get the same problems on the apisix 2.8
   > 
   > I found a bug in [api7/lua-resty-healthcheck@`master`/lib/resty/healthcheck.lua](https://github.com/api7/lua-resty-healthcheck/blob/master/lib/resty/healthcheck.lua?rgh-link-date=2021-11-10T08%3A27%3A57Z) The content of var `defaults` will be modified when not assigned the passive or active config item
   > 
   > Reproduce the bug: nginx.conf
   > 
   > ```lua
   > daemon off;
   > worker_processes  1;
   > error_log stderr;
   > events {
   >     worker_connections 1024;
   > }
   > http {
   >     access_log off;
   >     server {
   >         listen 19000;
   >         location / {
   >             default_type text/html;
   >             content_by_lua '
   >                 ngx.say("<p>Hello, World!</p>")
   >             ';
   >             log_by_lua '
   >                 local check = require("check")
   >             ';
   >         }
   >     }
   > }
   > ```
   > 
   > check.lua
   > 
   > ```lua
   > local cjson = require("cjson.safe")
   > 
   > -- copy from: https://github.com/api7/lua-resty-healthcheck/blob/master/lib/resty/healthcheck.lua#L1162
   > --============================================================================
   > -- Create health-checkers
   > --============================================================================
   > 
   > 
   > local NO_DEFAULT = {}
   > local MAXNUM = 2^31 - 1
   > 
   > 
   > local function fail(ctx, k, msg)
   >   ctx[#ctx + 1] = k
   >   error(table.concat(ctx, ".") .. ": " .. msg, #ctx + 1)
   > end
   > 
   > 
   > local function fill_in_settings(opts, defaults, ctx)
   >   ctx = ctx or {}
   >   local obj = {}
   >   for k, default in pairs(defaults) do
   >     local v = opts[k]
   > 
   >     -- basic type-check of configuration
   >     if default ~= NO_DEFAULT
   >     and v ~= nil
   >     and type(v) ~= type(default) then
   >       fail(ctx, k, "invalid value")
   >     end
   > 
   >     if v ~= nil then
   >       if type(v) == "table" then
   >         if default[1] then -- do not recurse on arrays
   >           obj[k] = v
   >         else
   >           ctx[#ctx + 1] = k
   >           obj[k] = fill_in_settings(v, default, ctx)
   >           ctx[#ctx + 1] = nil
   >         end
   >       else
   >         if type(v) == "number" and (v < 0 or v > MAXNUM) then
   >           fail(ctx, k, "must be between 0 and " .. MAXNUM)
   >         end
   >         obj[k] = v
   >       end
   >     elseif default ~= NO_DEFAULT then
   >       obj[k] = default
   >     end
   > 
   >   end
   >   return obj
   > end
   > 
   > 
   > local defaults = {
   >   name = NO_DEFAULT,
   >   shm_name = NO_DEFAULT,
   >   type = NO_DEFAULT,
   >   status_ver = 0,
   >   checks = {
   >     active = {
   >       type = "http",
   >       timeout = 1,
   >       concurrency = 10,
   >       http_path = "/",
   >       https_verify_certificate = true,
   >       healthy = {
   >         interval = 0, -- 0 = disabled by default
   >         http_statuses = { 200, 302 },
   >         successes = 2,
   >       },
   >       unhealthy = {
   >         interval = 0, -- 0 = disabled by default
   >         http_statuses = { 429, 404,
   >                           500, 501, 502, 503, 504, 505 },
   >         tcp_failures = 2,
   >         timeouts = 3,
   >         http_failures = 5,
   >       },
   >       req_headers = {""},
   >     },
   >     passive = {
   >       type = "http",
   >       healthy = {
   >         http_statuses = { 200, 201, 202, 203, 204, 205, 206, 207, 208, 226,
   >                           300, 301, 302, 303, 304, 305, 306, 307, 308 },
   >         successes = 5,
   >       },
   >       unhealthy = {
   >         http_statuses = { 429, 500, 503 },
   >         tcp_failures = 2,
   >         timeouts = 7,
   >         http_failures = 5,
   >       },
   >     },
   >   },
   > }
   > 
   > 
   > local function to_set(tbl, key)
   >   local set = {}
   >   for _, item in ipairs(tbl[key]) do
   >     set[item] = true
   >   end
   >   tbl[key] = set
   > end
   > 
   > 
   >   -- In the below is my code
   > local option_no_passive  =  cjson.decode([[
   >     {
   >         "checks":
   >         {
   >             "active":{"unhealthy":{"tcp_Failures":3,"http_statuses":[500,501,502,503,504,505],"timeouts":3,"interval":100,"tcp_failures":2,"http_failures":3},"concurrency":10,"http_path":"\/healthz","https_verify_certificate":true,"port":9080,"type":"http","healthy":{"interval":5,"successes":1,"http_statuses":[200,201,202,203,204,205,206,207,208,226,300,301,302,303,304,305,306,307,308,400,401,403,404,405,415,429]},"host":"healthcheck","timeout":5}
   >         },
   >         "name":"upstream#\/internal-apisix\/upstreams\/380542682478412600","shm_name":"upstream-healthcheck"
   >     }]])
   > -- The default can be encoded to json
   > ngx.log(ngx.ERR, "===defaults: ", cjson.encode(defaults))
   > 
   > -- The default `passive` config will be filled into `filled_option_no_passive` by the method `fill_in_settings`
   > local filled_option_no_passive = fill_in_settings(option_no_passive ,defaults)
   > ngx.log(ngx.ERR, "===filled_option_no_passive: ", cjson.encode(filled_option_no_passive))
   > 
   > -- copy from: https://github.com/api7/lua-resty-healthcheck/blob/master/lib/resty/healthcheck.lua#L1364
   > to_set(filled_option_no_passive.checks.active.unhealthy, "http_statuses")
   > to_set(filled_option_no_passive.checks.active.healthy, "http_statuses")
   > to_set(filled_option_no_passive.checks.passive.unhealthy, "http_statuses")
   > to_set(filled_option_no_passive.checks.passive.healthy, "http_statuses")
   > 
   > -- print: nil Cannot serialise table: excessively sparse array while logging request
   > -- The defaults has been modified by `to_set`
   > ngx.log(ngx.ERR, "===defaults: ", cjson.encode(defaults))
   > ```
   
   ---
   
   @chzhuo your question does not seem to be related to @Ben0625's question. Regarding the issue of "Unable to serialize table: too sparse array", please refer to the lua-cjson document: [kyne.com.au/~mark/software/lua-cjson -manual.html#encode_sparse_array](https://kyne.com.au/~mark/software/lua-cjson-manual.html#encode_sparse_array)
   
   ![image](https://user-images.githubusercontent.com/8529452/141283994-cb7e99b6-dbae-4039-857f-2b984293e66f.png)
   


-- 
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