diff --git a/apisix/core/id.lua b/apisix/core/id.lua index 5470f7ad9783..d6e728d2f0fc 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 3d9ffea13553..5d773ab38aa1 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 000000000000..8d7d40314798 --- /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 000000000000..80e503963d7e --- /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]