diff --git a/apisix/discovery/nacos.lua b/apisix/discovery/nacos.lua index c41a8c2689ce..2eee156ffae8 100644 --- a/apisix/discovery/nacos.lua +++ b/apisix/discovery/nacos.lua @@ -38,6 +38,8 @@ local default_weight local applications local auth_path = 'auth/login' local instance_list_path = 'ns/instance/list?healthyOnly=true&serviceName=' +local default_namespace_id = "public" +local default_group_name = "DEFAULT_GROUP" local events local events_list @@ -233,15 +235,11 @@ local function iter_and_add_service(services, values) up = conf end - local namespace_id - if up.discovery_args then - namespace_id = up.discovery_args.namespace_id - end + local namespace_id = (up.discovery_args and up.discovery_args.namespace_id) + or default_namespace_id - local group_name - if up.discovery_args then - group_name = up.discovery_args.group_name - end + local group_name = (up.discovery_args and up.discovery_args.group_name) + or default_group_name if up.discovery_type == 'nacos' then core.table.insert(services, { @@ -296,6 +294,8 @@ local function fetch_full_registry(premature) for _, service_info in ipairs(infos) do local data, err + local namespace_id = service_info.namespace_id + local group_name = service_info.group_name local namespace_param = get_namespace_param(service_info.namespace_id) local group_name_param = get_group_name_param(service_info.group_name) local query_path = instance_list_path .. service_info.service_name @@ -306,11 +306,21 @@ local function fetch_full_registry(premature) goto CONTINUE end + if not up_apps[namespace_id] then + up_apps[namespace_id] = {} + end + + if not up_apps[namespace_id][group_name] then + up_apps[namespace_id][group_name] = {} + end + for _, host in ipairs(data.hosts) do - local nodes = up_apps[service_info.service_name] + local nodes = up_apps[namespace_id] + [group_name][service_info.service_name] if not nodes then nodes = {} - up_apps[service_info.service_name] = nodes + up_apps[namespace_id] + [group_name][service_info.service_name] = nodes end core.table.insert(nodes, { host = host.ip, @@ -336,7 +346,12 @@ local function fetch_full_registry(premature) end -function _M.nodes(service_name) +function _M.nodes(service_name, discovery_args) + local namespace_id = discovery_args and + discovery_args.namespace_id or default_namespace_id + local group_name = discovery_args + and discovery_args.group_name or default_group_name + local logged = false -- maximum waiting time: 5 seconds local waiting_time = 5 @@ -349,7 +364,11 @@ function _M.nodes(service_name) ngx.sleep(step) waiting_time = waiting_time - step end - return applications[service_name] + + if not applications[namespace_id] or not applications[namespace_id][group_name] then + return nil + end + return applications[namespace_id][group_name][service_name] end diff --git a/apisix/upstream.lua b/apisix/upstream.lua index 48ab70aa6578..5be6d64950c1 100644 --- a/apisix/upstream.lua +++ b/apisix/upstream.lua @@ -239,7 +239,7 @@ function _M.set_by_route(route, api_ctx) return 503, err end - local new_nodes, err = dis.nodes(up_conf.service_name) + local new_nodes, err = dis.nodes(up_conf.service_name, up_conf.discovery_args) if not new_nodes then return HTTP_CODE_UPSTREAM_UNAVAILABLE, "no valid upstream node: " .. (err or "nil") end diff --git a/ci/install-ext-services-via-docker.sh b/ci/install-ext-services-via-docker.sh index 231e9fb9fafc..612d0b7136fe 100755 --- a/ci/install-ext-services-via-docker.sh +++ b/ci/install-ext-services-via-docker.sh @@ -56,14 +56,18 @@ mkdir tmp cd tmp wget https://raw.githubusercontent.com/api7/nacos-test-service/main/spring-nacos-1.0-SNAPSHOT.jar curl https://raw.githubusercontent.com/api7/nacos-test-service/main/Dockerfile | docker build -t nacos-test-service:1.0-SNAPSHOT -f - . -docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env DISCOVERY_PORT=18001 --env NACOS_ADDR=nacos2:8848 --env SUFFIX_NUM=1 -p 18001:18001 --name nacos-service1 nacos-test-service:1.0-SNAPSHOT -docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env DISCOVERY_PORT=18002 --env NACOS_ADDR=nacos2:8848 --env SUFFIX_NUM=2 -p 18002:18001 --name nacos-service2 nacos-test-service:1.0-SNAPSHOT +docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env NACOS_ADDR=nacos2:8848 --env SUFFIX_NUM=1 -p 18001:18001 --name nacos-service1 nacos-test-service:1.0-SNAPSHOT +docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env NACOS_ADDR=nacos2:8848 --env SUFFIX_NUM=2 -p 18002:18001 --name nacos-service2 nacos-test-service:1.0-SNAPSHOT # register nacos service with namespaceId=test_ns -docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env DISCOVERY_PORT=18003 --env NACOS_ADDR=nacos2:8848 --env NAMESPACE=test_ns --env SUFFIX_NUM=1 -p 18003:18001 --name nacos-service3 nacos-test-service:1.0-SNAPSHOT +docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env NACOS_ADDR=nacos2:8848 --env NAMESPACE=test_ns --env SUFFIX_NUM=1 -p 18003:18001 --name nacos-service3 nacos-test-service:1.0-SNAPSHOT # register nacos service with group=test_group -docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env DISCOVERY_PORT=18004 --env NACOS_ADDR=nacos2:8848 --env GROUP=test_group --env SUFFIX_NUM=1 -p 18004:18001 --name nacos-service4 nacos-test-service:1.0-SNAPSHOT +docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env NACOS_ADDR=nacos2:8848 --env GROUP=test_group --env SUFFIX_NUM=1 -p 18004:18001 --name nacos-service4 nacos-test-service:1.0-SNAPSHOT # register nacos service with namespaceId=test_ns and group=test_group -docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env DISCOVERY_PORT=18005 --env NACOS_ADDR=nacos2:8848 --env NAMESPACE=test_ns --env GROUP=test_group --env SUFFIX_NUM=1 -p 18005:18001 --name nacos-service5 nacos-test-service:1.0-SNAPSHOT +docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env NACOS_ADDR=nacos2:8848 --env NAMESPACE=test_ns --env GROUP=test_group --env SUFFIX_NUM=1 -p 18005:18001 --name nacos-service5 nacos-test-service:1.0-SNAPSHOT +# register nacos service with namespaceId=test_ns and group=test_group2 +docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env NACOS_ADDR=nacos2:8848 --env NAMESPACE=test_ns --env GROUP=test_group2 --env SUFFIX_NUM=3 -p 18006:18001 --name nacos-service6 nacos-test-service:1.0-SNAPSHOT +# register nacos service with namespaceId=test_ns2 and group=test_group +docker run -d --rm --network nacos_net --env SERVICE_NAME=APISIX-NACOS --env NACOS_ADDR=nacos2:8848 --env NAMESPACE=test_ns2 --env GROUP=test_group --env SUFFIX_NUM=4 -p 18007:18001 --name nacos-service7 nacos-test-service:1.0-SNAPSHOT url="127.0.0.1:18005/hello" until [[ "$(curl -s -o /dev/null -w ''%{http_code}'' $url)" == "200" ]]; do diff --git a/t/discovery/nacos.t b/t/discovery/nacos.t index b139a99b4ba6..98c309c78920 100644 --- a/t/discovery/nacos.t +++ b/t/discovery/nacos.t @@ -758,3 +758,187 @@ discovery: ] --- no_error_log [error] + + + +=== TEST 25: same namespace_id and service_name, different group_name +--- extra_yaml_config +discovery: + nacos: + host: + - "http://127.0.0.1:8858" + fetch_interval: 1 +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + + -- use nacos-service5 + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "uri": "/hello", + "upstream": { + "service_name": "APISIX-NACOS", + "discovery_type": "nacos", + "type": "roundrobin", + "discovery_args": { + "namespace_id": "test_ns", + "group_name": "test_group" + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + + -- use nacos-service6 + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "uri": "/hello1", + "upstream": { + "service_name": "APISIX-NACOS", + "discovery_type": "nacos", + "type": "roundrobin", + "discovery_args": { + "namespace_id": "test_ns", + "group_name": "test_group2" + } + }, + "plugins": { + "proxy-rewrite": { + "uri": "/hello" + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + + ngx.sleep(1.5) + + local http = require "resty.http" + local httpc = http.new() + local uri1 = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello" + local res, err = httpc:request_uri(uri1, { method = "GET"}) + if err then + ngx.log(ngx.ERR, err) + ngx.status = res.status + return + end + ngx.say(res.body) + + local uri2 = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello1" + res, err = httpc:request_uri(uri2, { method = "GET"}) + if err then + ngx.log(ngx.ERR, err) + ngx.status = res.status + return + end + ngx.say(res.body) + } + } +--- request +GET /t +--- response_body +server 1 +server 3 +--- no_error_log +[error] + + + +=== TEST 26: same group_name and service_name, different namespace_id +--- extra_yaml_config +discovery: + nacos: + host: + - "http://127.0.0.1:8858" + fetch_interval: 1 +--- config + location /t { + content_by_lua_block { + local t = require("lib.test_admin").test + + -- use nacos-service5 + local code, body = t('/apisix/admin/routes/1', + ngx.HTTP_PUT, + [[{ + "uri": "/hello", + "upstream": { + "service_name": "APISIX-NACOS", + "discovery_type": "nacos", + "type": "roundrobin", + "discovery_args": { + "namespace_id": "test_ns", + "group_name": "test_group" + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + + -- use nacos-service7 + local code, body = t('/apisix/admin/routes/2', + ngx.HTTP_PUT, + [[{ + "uri": "/hello1", + "upstream": { + "service_name": "APISIX-NACOS", + "discovery_type": "nacos", + "type": "roundrobin", + "discovery_args": { + "namespace_id": "test_ns2", + "group_name": "test_group" + } + }, + "plugins": { + "proxy-rewrite": { + "uri": "/hello" + } + } + }]] + ) + + if code >= 300 then + ngx.status = code + end + + ngx.sleep(1.5) + + local http = require "resty.http" + local httpc = http.new() + local uri1 = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello" + local res, err = httpc:request_uri(uri1, { method = "GET"}) + if err then + ngx.log(ngx.ERR, err) + ngx.status = res.status + return + end + ngx.say(res.body) + + local uri2 = "http://127.0.0.1:" .. ngx.var.server_port .. "/hello1" + res, err = httpc:request_uri(uri2, { method = "GET"}) + if err then + ngx.log(ngx.ERR, err) + ngx.status = res.status + return + end + ngx.say(res.body) + } + } +--- request +GET /t +--- response_body +server 1 +server 4 +--- no_error_log +[error]