You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by me...@apache.org on 2020/10/09 08:39:57 UTC

[apisix] branch master updated: bugfix: set random seed for each worker process at `init_worker` phase, only `init` phase is not enough. (#2357)

This is an automated email from the ASF dual-hosted git repository.

membphis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git


The following commit(s) were added to refs/heads/master by this push:
     new 251625d  bugfix: set random seed for each worker process at `init_worker` phase, only `init` phase is not enough. (#2357)
251625d is described below

commit 251625d8ab969b0b46d12041beff44f329e95321
Author: YuanSheng Wang <me...@gmail.com>
AuthorDate: Fri Oct 9 16:39:49 2020 +0800

    bugfix: set random seed for each worker process at `init_worker` phase, only `init` phase is not enough. (#2357)
---
 apisix/core/id.lua     |  1 +
 apisix/init.lua        | 25 ++++++++++++-----
 t/core/random.t        | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
 t/stream-node/random.t | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 171 insertions(+), 7 deletions(-)

diff --git a/apisix/core/id.lua b/apisix/core/id.lua
index 5470f7a..d6e728d 100644
--- a/apisix/core/id.lua
+++ b/apisix/core/id.lua
@@ -65,6 +65,7 @@ function _M.init()
         return
     end
 
+    uuid.seed()
     apisix_uid = uuid.generate_v4()
     log.notice("not found apisix uid, generate a new one: ", apisix_uid)
 
diff --git a/apisix/init.lua b/apisix/init.lua
index 3d9ffea..5d773ab 100644
--- a/apisix/init.lua
+++ b/apisix/init.lua
@@ -63,13 +63,6 @@ function _M.http_init(args)
                              "maxrecord=8000", "sizemcode=64",
                              "maxmcode=4000", "maxirconst=1000")
 
-    --
-    local seed, err = core.utils.get_seed_from_urandom()
-    if not seed then
-        core.log.warn('failed to get seed from urandom: ', err)
-        seed = ngx_now() * 1000 + ngx.worker.pid()
-    end
-    math.randomseed(seed)
     parse_args(args)
     core.id.init()
 
@@ -82,6 +75,15 @@ end
 
 
 function _M.http_init_worker()
+    local seed, err = core.utils.get_seed_from_urandom()
+    if not seed then
+        core.log.warn('failed to get seed from urandom: ', err)
+        seed = ngx_now() * 1000 + ngx.worker.pid()
+    end
+    math.randomseed(seed)
+    -- for testing only
+    core.log.info("random test in [1, 10000]: ", math.random(1, 1000000))
+
     local we = require("resty.worker.events")
     local ok, err = we.configure({shm = "worker-events", interval = 0.1})
     if not ok then
@@ -759,6 +761,15 @@ end
 
 function _M.stream_init_worker()
     core.log.info("enter stream_init_worker")
+    local seed, err = core.utils.get_seed_from_urandom()
+    if not seed then
+        core.log.warn('failed to get seed from urandom: ', err)
+        seed = ngx_now() * 1000 + ngx.worker.pid()
+    end
+    math.randomseed(seed)
+    -- for testing only
+    core.log.info("random stream test in [1, 10000]: ", math.random(1, 1000000))
+
     router.stream_init_worker()
     plugin.init_worker()
 
diff --git a/t/core/random.t b/t/core/random.t
new file mode 100644
index 0000000..8d7d403
--- /dev/null
+++ b/t/core/random.t
@@ -0,0 +1,76 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+use t::APISIX 'no_plan';
+
+master_on();
+workers(4);
+repeat_each(1);
+no_long_string();
+no_root_location();
+log_level("info");
+
+run_tests;
+
+__DATA__
+
+=== TEST 1: generate different random number in different worker process
+--- config
+    location /t {
+        content_by_lua_block {
+            local log_file = ngx.config.prefix() .. "logs/error.log"
+            local file = io.open(log_file, "r")
+            local log = file:read("*a")
+
+            local it, err = ngx.re.gmatch(log, [[random test in \[1, 10000\]: (\d+)]], "jom")
+            if not it then
+                ngx.log(ngx.ERR, "failed to gmatch: ", err)
+                return
+            end
+
+            local random_nums = {}
+            while true do
+                local m, err = it()
+                if err then
+                    ngx.log(ngx.ERR, "error: ", err)
+                    return
+                end
+
+                if not m then
+                    break
+                end
+
+                -- found a match
+                table.insert(random_nums, m[1])
+            end
+
+            for i = 2, #random_nums do
+                local pre = random_nums[i - 1]
+                local cur = random_nums[i]
+                ngx.say("random[", i - 1, "] == random[", i, "]: ", pre == cur)
+            end
+        }
+    }
+--- request
+GET /t
+--- response_body
+random[1] == random[2]: false
+random[2] == random[3]: false
+random[3] == random[4]: false
+random[4] == random[5]: false
+--- no_error_log
+[error]
diff --git a/t/stream-node/random.t b/t/stream-node/random.t
new file mode 100644
index 0000000..80e5039
--- /dev/null
+++ b/t/stream-node/random.t
@@ -0,0 +1,76 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+use t::APISIX 'no_plan';
+
+master_on();
+workers(4);
+log_level('info');
+repeat_each(1);
+no_long_string();
+no_root_location();
+
+run_tests();
+
+__DATA__
+
+=== TEST 1: generate different random number in different worker process
+--- stream_enable
+--- config
+    location /test {
+        content_by_lua_block {
+            local log_file = ngx.config.prefix() .. "logs/error.log"
+            local file = io.open(log_file, "r")
+            local log = file:read("*a")
+
+            local it, err = ngx.re.gmatch(log, [[random stream test in \[1, 10000\]: (\d+)]], "jom")
+            if not it then
+                ngx.log(ngx.ERR, "failed to gmatch: ", err)
+                return
+            end
+
+            local random_nums = {}
+            while true do
+                local m, err = it()
+                if err then
+                    ngx.log(ngx.ERR, "error: ", err)
+                    return
+                end
+
+                if not m then
+                    break
+                end
+
+                -- found a match
+                table.insert(random_nums, m[1])
+            end
+
+            for i = 2, #random_nums do
+                local pre = random_nums[i - 1]
+                local cur = random_nums[i]
+                ngx.say("random[", i - 1, "] == random[", i, "]: ", pre == cur)
+            end
+        }
+    }
+--- request
+GET /test
+--- response_body
+random[1] == random[2]: false
+random[2] == random[3]: false
+random[3] == random[4]: false
+random[4] == random[5]: false
+--- no_error_log
+[error]