-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add nacos support #3820
feat: add nacos support #3820
Conversation
add nacos support
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add test under t/discovery.
And you need to add docs under https://github.com/apache/apisix/tree/master/docs/en/latest/discovery |
Please make sure it can pass the lint. |
docs/en/latest/discovery/nacos.md
Outdated
discovery: | ||
nacos: | ||
host: | ||
- "http://192.168.33.1:8848" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't mention the user / password feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because Nacos not need login yet.
apisix/discovery/nacos.lua
Outdated
}, | ||
fetch_interval = {type = "integer", minimum = 1, default = 30}, | ||
prefix = {type = "string"}, | ||
weight = {type = "integer", minimum = 0}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing default for weight?
And the minimum weight should be 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK,I copy from eureka.
apisix/discovery/nacos.lua
Outdated
|
||
local httpc = http.new() | ||
local timeout = local_conf.discovery.nacos.timeout | ||
local connect_timeout = timeout and timeout.connect or 2000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default value will be injected via schema check. We don't need to assign it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
apisix/discovery/nacos.lua
Outdated
log.info("default_weight:", default_weight, ".") | ||
local fetch_interval = local_conf.discovery.nacos.fetch_interval or 30 | ||
log.info("fetch_interval:", fetch_interval, ".") | ||
service_list_path = local_conf.discovery.nacos.service_list_path or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where should I configure service_list_path
? There is neither schema nor doc for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will fix it.
apisix/discovery/nacos.lua
Outdated
log.info("fetch_interval:", fetch_interval, ".") | ||
service_list_path = local_conf.discovery.nacos.service_list_path or | ||
'ns/service/list?pageNo=1&pageSize=20' | ||
instance_list_path = local_conf.discovery.nacos.instance_list_path or |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
apisix/discovery/nacos.lua
Outdated
end | ||
|
||
local up_apps = core.table.new(0, 0) | ||
local data = get_url(base_uri,basic_auth,service_list_path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need space after the comma.
And please check the returned value of get_url
.
apisix/discovery/nacos.lua
Outdated
log.info("nacos uri:", request_uri, ".") | ||
local url = request_uri .. path | ||
local headers = core.table.new(0, 5) | ||
headers['Connection'] = 'Keep-Alive' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need it for HTTP 1.1
apisix/discovery/nacos.lua
Outdated
local function request(request_uri, basic_auth, method, path, query, body) | ||
log.info("nacos uri:", request_uri, ".") | ||
local url = request_uri .. path | ||
local headers = core.table.new(0, 5) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why choose 5?
apisix/discovery/nacos.lua
Outdated
if local_conf.discovery.nacos.prefix then | ||
url = url .. local_conf.discovery.nacos.prefix | ||
end | ||
if string_sub(url, #url) ~= "/" then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to use str_byte(uri, #uri) == str_byte("/")
docs/en/latest/discovery/nacos.md
Outdated
fetch_interval: 30 # default 30 sec | ||
weight: 100 # default 100 | ||
timeout: | ||
connect: 2000 # default 2000 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better to mention the unit is ms.
t/discovery/nacos.t
Outdated
--- pipelined_requests eval | ||
[ | ||
"POST /nacos/v1/ns/instance?port=18001&healthy=true&ip=127.0.0.1&weight=1.0&serviceName=APISIX-NACOS&encoding=GBK&enabled=true", | ||
"DELETE /nacos/v1/ns/service?serviceName=APISIX-NACOS", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why POST and then DELETE?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If has no data,delete return code is 400,if has data,delete return code is 200.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it is not the feature of APISIX. We don't need to test nacos itself.
t/discovery/nacos.t
Outdated
#END | ||
--- request | ||
GET /hello | ||
--- error_code: 200 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to show if server 1 or server 2 is hit.
And we need a test to show the default weight
docs/en/latest/discovery/nacos.md
Outdated
```shell | ||
$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d ' | ||
{ | ||
"uri": "/nacos/**", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use /nacos/*
is enough?
.travis/linux_tengine_runner.sh
Outdated
@@ -40,6 +40,9 @@ before_install() { | |||
# start consul servers | |||
docker run --rm --name consul_1 -d -p 8500:8500 consul:1.7 consul agent -server -bootstrap-expect=1 -client 0.0.0.0 -log-level info -data-dir=/consul/data | |||
docker run --rm --name consul_2 -d -p 8600:8500 consul:1.7 consul agent -server -bootstrap-expect=1 -client 0.0.0.0 -log-level info -data-dir=/consul/data | |||
|
|||
# start nacos server | |||
docker run --rm --name nacos_1 -d --env PREFER_HOST_MODE=hostname --env MODE=standalone --env JVM_XMS=512m --env JVM_XMX=512m --env JVM_XMN=256m -p8848:8848 nacos/nacos-server:latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need test the user/password feature.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If add NACOS_AUTH_ENABLE=true, file nacos.t need login too.
Could you give me a t file login demo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use different conf in different tests, one for auth success and another for auth fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How to check nacos in discovery plugin whether authed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the auth enable nacos can be used, the auth is successful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But if nacos start with auth mode,in nacos.t add services to nacos need send auth token.
How can i save auth token in nacos.t?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can export the auth function: https://github.com/apache/apisix/pull/3820/files#diff-46fd008790f9ea29612a92ca5c94212ae43c81ab6b902ef3014d3d6b4bdfc5b3R202
and call it in the test file.
apisix/discovery/nacos.lua
Outdated
} | ||
|
||
|
||
local function str_split (inputstr, sep) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use existent API:
apisix/apisix/plugins/proxy-cache.lua
Line 194 in e9a59ac
local levels = ngx_re.split(cache_levels, ":") |
apisix/discovery/nacos.lua
Outdated
prefix = {type = "string", default = "/nacos/v1/"}, | ||
auth_path = {type = "string", default = "auth/login"}, | ||
service_list_path = {type = "string", default = "ns/service/list?pageNo=1&pageSize=20"}, | ||
instance_list_path = {type = "string", default = "ns/instance/list?serviceName="}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need a test to check the user-defined paths.
BTW, in what situation people need to redefine the paths?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When Nacos api change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benx203
I think we can remove it now and add it if needed.
We need to add a doc and test for this feature if you insist to keep it.
(I don't recommend to do that as this PR is big enough)
apisix/discovery/nacos.lua
Outdated
fetch_interval = {type = "integer", minimum = 1, default = 30}, | ||
prefix = {type = "string", default = "/nacos/v1/"}, | ||
auth_path = {type = "string", default = "auth/login"}, | ||
service_list_path = {type = "string", default = "ns/service/list?pageNo=1&pageSize=20"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only return the first 20 services is not a good idea.
We need to iterate the upstreams and build a service list from those that have nacos
discovery_type.
Like this:
Lines 144 to 149 in e9a59ac
values = get_upstreams() | |
else | |
return 400, {error_msg = str_format("invalid src type %s", src_type)} | |
end | |
local info, err = iter_and_find_healthcheck_info(values, src_type, src_id) |
You might need some lazy load trick to break the dependent cycle.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.
apisix/discovery/nacos.lua
Outdated
end | ||
|
||
for _, host in ipairs(data.hosts) do | ||
if tostring(host.valid) == 'true' and |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I set up the environment and debug it myself.
Here is the host
: {"enabled":true,"instanceHeartBeatTimeOut":15000,"ipDeleteTimeout":30000,"instanceHeartBeatInterval":5000,"metadata":{"preserved.register.source":"SPRING_CLOUD"},"port":18001,"serviceName":"DEFAULT_GROUP@@APISIX-NACOS","instanceId":"192.168.65.3#18001#DEFAULT#DEFAULT_GROUP@@APISIX-NACOS","healthy":true,"ip":"192.168.65.3","ephemeral":true,"clusterName":"DEFAULT","weight":1}
There is not valid
field. The response doesn't match their API doc: https://nacos.io/en-us/docs/open-api.html
I am not sure if it is because the latest Nacos has changed the API. Maybe we need to use the tagged nacos image 2.0.0
instead of the latest one?
.github/workflows/centos7-ci.yml
Outdated
nohup docker network rm nacos_net > /dev/null 2>&1 & | ||
nohup docker network create nacos_net > /dev/null 2>&1 & | ||
# nacos no auth server - for test no auth | ||
docker run --rm -d --name nacos_no_auth --network nacos_net --hostname nacos2 --env NACOS_SERVERS="nacos1:8848 nacos2:8848" --env PREFER_HOST_MODE=hostname --env MODE=cluster --env EMBEDDED_STORAGE=embedded --env JVM_XMS=512m --env JVM_XMX=512m --env JVM_XMN=256m -p8858:8848 nacos/nacos-server:latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be better to use nacos/nacos-server:2.0.0
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nacos version should be 1.4.1,2.0.0 just released few days ago.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benx203
Why can't we support 2.0.0 directly? Is 2.0.0
incompatible with 1.4.1
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think better way is support both 2.0.0 and 1.4.1.
Maybe support 2.0.0 later?
.github/workflows/centos7-ci.yml
Outdated
rm -rf tmp | ||
mkdir tmp | ||
cd tmp | ||
wget https://raw.githubusercontent.com/benx203/nacos-test-service/main/spring-nacos-1.0-SNAPSHOT.jar |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@benx203
Would you also submit the Java code to https://github.com/benx203/nacos-test-service? Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
apisix/discovery/nacos.lua
Outdated
for _, host in ipairs(data.hosts) do | ||
if tostring(host.valid) == 'true' and | ||
tostring(host.healthy) == 'true' and | ||
tostring(host.enabled) == 'true' then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more question: why we need to filter the result according to those fields?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If query all records,need to filter.
But now should not need any more.
Signed-off-by: spacewander <spacewanderlzx@gmail.com>
@benx203 |
@spacewander |
apisix/discovery/nacos.lua
Outdated
type = "array", | ||
minItems = 1, | ||
items = { | ||
type = "string", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add a pattern to limit the string to the host format
apisix/discovery/nacos.lua
Outdated
}, | ||
}, | ||
fetch_interval = {type = "integer", minimum = 1, default = 30}, | ||
prefix = {type = "string", default = "/nacos/v1/"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
apisix/discovery/nacos.lua
Outdated
|
||
|
||
local _M = { | ||
version = 0.1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this version is useless, we can drop it
local url = request_uri .. path | ||
log.info("request url:", url) | ||
local headers = core.table.new(0, 0) | ||
headers['Accept'] = 'application/json' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for the string object, I think we use "
, it is easier for reading.
headers["Accept"] = "application/json"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and please fix the similar points
apisix/discovery/nacos.lua
Outdated
|
||
|
||
local function get_token_param(base_uri, username, password) | ||
if username and password then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
better style:
if not username or not password then
return ""
end
...
apisix/discovery/nacos.lua
Outdated
|
||
local function get_token_param(base_uri, username, password) | ||
if username and password then | ||
local data, err = post_url(base_uri, auth_path .. "?username=" .. username |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should call ngx.encode_args for username
and password
apisix/discovery/nacos.lua
Outdated
|
||
|
||
local function iter_and_add_service(services, values) | ||
if not values then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bad indentation
apisix/discovery/nacos.lua
Outdated
local host = local_conf.discovery.nacos.host | ||
-- TODO Add health check to get healthy nodes. | ||
local url = host[math_random(#host)] | ||
local auth_idx = str_find(url, "@") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we'd better use the plain text model, better performance.
https://stackoverflow.com/questions/18973019/is-there-a-lua-string-find-without-pattern
apisix/discovery/nacos.lua
Outdated
|
||
function _M.nodes(service_name) | ||
local logged = false | ||
while not applications do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to set a maximum waiting time , eg: 5 seconds
@benx203 thanks for your contribution. |
OK,i will try,thank you all. |
apisix/discovery/nacos.lua
Outdated
@@ -275,41 +273,33 @@ end | |||
|
|||
|
|||
function _M.nodes(service_name) | |||
local logged = false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original code is good. We just need to set a 5s limitation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just keep simple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The lazy init is important as the sync is slow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK,i rollback the code.
apisix/discovery/nacos.lua
Outdated
local host = local_conf.discovery.nacos.host | ||
-- TODO Add health check to get healthy nodes. | ||
local url = host[math_random(#host)] | ||
local auth_idx = str_find(url, '@', 1, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The core.string.find
is already the plain string find... 😅
Not all the suggestion from the reviewer is correct.
local values = get_upstreams() | ||
iter_and_add_service(services, values) | ||
values = get_routes() | ||
iter_and_add_service(services, values) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By the way,Are there 'discovery_type' config in service and route?
@spacewander
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those can have embedded upstream field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see,thanks.
feat:add nacos support