This is an automated email from the ASF dual-hosted git repository. vinci 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 fff4d14 feature: support multiple service discovery (#2556) fff4d14 is described below commit fff4d14a0dcbd6a9854782d7ff22d09b27a19082 Author: shoogoome <34764574+shoogo...@users.noreply.github.com> AuthorDate: Fri Oct 30 20:34:10 2020 +0800 feature: support multiple service discovery (#2556) support multiple service discovery,then we can switch it in upstream --- apisix/balancer.lua | 10 +++++++- apisix/discovery/eureka.lua | 18 +++++++------- apisix/discovery/init.lua | 18 ++++++++++---- apisix/schema_def.lua | 4 ++++ conf/config-default.yaml | 23 +++++++++--------- doc/discovery.md | 47 ++++++++++++++++++++---------------- doc/zh-cn/discovery.md | 58 +++++++++++++++++++++++++-------------------- t/discovery/eureka.t | 26 ++++++++++---------- 8 files changed, 121 insertions(+), 83 deletions(-) diff --git a/apisix/balancer.lua b/apisix/balancer.lua index f2eec90..4eba0bb 100644 --- a/apisix/balancer.lua +++ b/apisix/balancer.lua @@ -164,7 +164,15 @@ local function pick_server(route, ctx) if not discovery then return nil, "discovery is uninitialized" end - up_conf.nodes = discovery.nodes(up_conf.service_name) + if not up_conf.discovery_type then + return nil, "discovery server need appoint" + end + + local dis = discovery[up_conf.discovery_type] + if not dis then + return nil, "discovery is uninitialized" + end + up_conf.nodes = dis.nodes(up_conf.service_name) end local nodes_count = up_conf.nodes and #up_conf.nodes or 0 diff --git a/apisix/discovery/eureka.lua b/apisix/discovery/eureka.lua index d4b4368..179d763 100644 --- a/apisix/discovery/eureka.lua +++ b/apisix/discovery/eureka.lua @@ -66,7 +66,8 @@ local _M = { local function service_info() - local host = local_conf.eureka and local_conf.eureka.host + local host = local_conf.discovery and + local_conf.discovery.eureka and local_conf.discovery.eureka.host if not host then log.error("do not set eureka.host") return @@ -84,8 +85,8 @@ local function service_info() url = protocol .. other basic_auth = "Basic " .. ngx.encode_base64(user_and_password) end - if local_conf.eureka.prefix then - url = url .. local_conf.eureka.prefix + if local_conf.discovery.eureka.prefix then + url = url .. local_conf.discovery.eureka.prefix end if string_sub(url, #url) ~= "/" then url = url .. "/" @@ -117,7 +118,7 @@ local function request(request_uri, basic_auth, method, path, query, body) end local httpc = http.new() - local timeout = local_conf.eureka.timeout + local timeout = local_conf.discovery.eureka.timeout local connect_timeout = timeout and timeout.connect or 2000 local send_timeout = timeout and timeout.send or 2000 local read_timeout = timeout and timeout.read or 5000 @@ -231,19 +232,20 @@ end function _M.init_worker() - if not local_conf.eureka or not local_conf.eureka.host or #local_conf.eureka.host == 0 then + if not local_conf.discovery.eureka or + not local_conf.discovery.eureka.host or #local_conf.discovery.eureka.host == 0 then error("do not set eureka.host") return end - local ok, err = core.schema.check(schema, local_conf.eureka) + local ok, err = core.schema.check(schema, local_conf.discovery.eureka) if not ok then error("invalid eureka configuration: " .. err) return end - default_weight = local_conf.eureka.weight or 100 + default_weight = local_conf.discovery.eureka.weight or 100 log.info("default_weight:", default_weight, ".") - local fetch_interval = local_conf.eureka.fetch_interval or 30 + local fetch_interval = local_conf.discovery.eureka.fetch_interval or 30 log.info("fetch_interval:", fetch_interval, ".") ngx_timer_at(0, fetch_full_registry) ngx_timer_every(fetch_interval, fetch_full_registry) diff --git a/apisix/discovery/init.lua b/apisix/discovery/init.lua index 16aafe6..10e7aa1 100644 --- a/apisix/discovery/init.lua +++ b/apisix/discovery/init.lua @@ -17,15 +17,25 @@ local log = require("apisix.core.log") local local_conf = require("apisix.core.config_local").local_conf() +local pairs = pairs -local discovery_type = local_conf.apisix and local_conf.apisix.discovery -local discovery +local discovery_type = local_conf.discovery +local discovery = {} if discovery_type then - log.info("use discovery: ", discovery_type) - discovery = require("apisix.discovery." .. discovery_type) + for discovery_name, _ in pairs(discovery_type) do + log.info("use discovery: ", discovery_name) + discovery[discovery_name] = require("apisix.discovery." .. discovery_name) + end end +function discovery.init_worker() + if discovery_type then + for discovery_name, _ in pairs(discovery_type) do + discovery[discovery_name].init_worker() + end + end +end return { version = 0.1, diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua index 0f50db2..b523191 100644 --- a/apisix/schema_def.lua +++ b/apisix/schema_def.lua @@ -353,6 +353,10 @@ local upstream_schema = { }, maxProperties = 16 }, + discovery_type = { + description = "discovery type", + type = "string", + }, pass_host = { description = "mod of host passing", type = "string", diff --git a/conf/config-default.yaml b/conf/config-default.yaml index f94bda9..8ae4ebc 100644 --- a/conf/config-default.yaml +++ b/conf/config-default.yaml @@ -109,7 +109,6 @@ apisix: key_encrypt_salt: "edd1c9f0985e76a2" # If not set, will save origin ssl key into etcd. # If set this, must be a string of length 16. And it will encrypt ssl key with AES-128-CBC # !!! So do not change it after saving your ssl, it can't decrypt the ssl keys have be saved if you change !! -# discovery: eureka # service discovery center nginx_config: # config for render the template to genarate nginx.conf error_log: "logs/error.log" error_log_level: "warn" # warn,error @@ -150,16 +149,18 @@ etcd: timeout: 30 # 30 seconds # user: root # root username for etcd # password: 5tHkHhYkjr6cQY # root password for etcd -#eureka: -# host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster. -# - "http://127.0.0.1:8761" -# prefix: "/eureka/" -# fetch_interval: 30 # default 30s -# weight: 100 # default weight for node -# timeout: -# connect: 2000 # default 2000ms -# send: 2000 # default 2000ms -# read: 5000 # default 5000ms + +# discovery: # service discovery center +# eureka: +# host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster. +# - "http://127.0.0.1:8761" +# prefix: "/eureka/" +# fetch_interval: 30 # default 30s +# weight: 100 # default weight for node +# timeout: +# connect: 2000 # default 2000ms +# send: 2000 # default 2000ms +# read: 5000 # default 5000ms plugins: # plugin list - example-plugin diff --git a/doc/discovery.md b/doc/discovery.md index cf3b0b5..5ed7f6d 100644 --- a/doc/discovery.md +++ b/doc/discovery.md @@ -27,7 +27,7 @@ * [**Implementation of eureka.lua**](#implementation-of-eurekalua) * [**How convert Eureka's instance data to APISIX's node?**](#how-convert-eurekas-instance-data-to-apisixs-node) * [**Configuration for discovery client**](#configuration-for-discovery-client) - * [**Select discovery client**](#select-discovery-client) + * [**Initial service discovery**](#initial-service-discovery) * [**Configuration for Eureka**](#configuration-for-eureka) * [**Upstream setting**](#upstream-setting) @@ -149,13 +149,14 @@ The result of this example is as follows: ## Configuration for discovery client -### Select discovery client +### Initial service discovery -Add the following configuration to `conf/config.yaml` and select one discovery client type which you want: +Add the following configuration to `conf/config.yaml` to add different service discovery clients for dynamic selection during use: ```yaml -apisix: - discovery: eureka +discovery: + eureka: + ... ``` This name should be consistent with the file name of the implementation registry in the `apisix/discovery/` directory. @@ -167,23 +168,24 @@ The supported discovery client: Eureka. Add following configuration in `conf/config.yaml` : ```yaml -eureka: - host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster. - - "http://${usename}:${passowrd}@${eureka_host1}:${eureka_port1}" - - "http://${usename}:${passowrd}@${eureka_host2}:${eureka_port2}" - prefix: "/eureka/" - fetch_interval: 30 # 30s - weight: 100 # default weight for node - timeout: - connect: 2000 # 2000ms - send: 2000 # 2000ms - read: 5000 # 5000ms +discovery: + eureka: + host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster. + - "http://${usename}:${passowrd}@${eureka_host1}:${eureka_port1}" + - "http://${usename}:${passowrd}@${eureka_host2}:${eureka_port2}" + prefix: "/eureka/" + fetch_interval: 30 # 30s + weight: 100 # default weight for node + timeout: + connect: 2000 # 2000ms + send: 2000 # 2000ms + read: 5000 # 5000ms ``` ## Upstream setting -Here is an example of routing a request with a URL of "/user/*" to a service which named "user-service" in the registry : +Here is an example of routing a request with a URL of "/user/*" to a service which named "user-service" and use eureka discovery client in the registry : ```shell $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d ' @@ -191,7 +193,8 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f "uri": "/user/*", "upstream": { "service_name": "USER-SERVICE", - "type": "roundrobin" + "type": "roundrobin", + "discovery_type": "eureka" } }' @@ -202,7 +205,7 @@ Transfer-Encoding: chunked Connection: keep-alive Server: APISIX web server -{"node":{"value":{"uri":"\/user\/*","upstream": {"service_name": "USER-SERVICE", "type": "roundrobin"}},"createdIndex":61925,"key":"\/apisix\/routes\/1","modifiedIndex":61925},"action":"create"} +{"node":{"value":{"uri":"\/user\/*","upstream": {"service_name": "USER-SERVICE", "type": "roundrobin", "discovery_type": "eureka"}},"createdIndex":61925,"key":"\/apisix\/routes\/1","modifiedIndex":61925},"action":"create"} ``` Because the upstream interface URL may have conflict, usually in the gateway by prefix to distinguish: @@ -218,7 +221,8 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f } "upstream": { "service_name": "A-SERVICE", - "type": "roundrobin" + "type": "roundrobin", + "discovery_type": "eureka" } }' @@ -232,7 +236,8 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f } "upstream": { "service_name": "B-SERVICE", - "type": "roundrobin" + "type": "roundrobin", + "discovery_type": "eureka" } }' ``` diff --git a/doc/zh-cn/discovery.md b/doc/zh-cn/discovery.md index a6ba442..c353844 100644 --- a/doc/zh-cn/discovery.md +++ b/doc/zh-cn/discovery.md @@ -27,7 +27,7 @@ * [**实现 eureka.lua**](#实现-eurekalua) * [**Eureka 与 APISIX 之间数据转换逻辑**](#Eureka-与-APISIX-之间数据转换逻辑) * [**注册中心配置**](#注册中心配置) - * [**选择注册中心**](#选择注册中心) + * [**初始化服务发现**](#初始化服务发现) * [**Eureka 的配置**](#Eureka-的配置) * [**upstream 配置**](#upstream-配置) @@ -147,13 +147,14 @@ APISIX是通过 `upstream.nodes` 来配置上游服务的,所以使用注册 ## 注册中心配置 -### 选择注册中心 +### 初始化服务发现 -首先要在 `conf/config.yaml` 文件中增加如下配置,以选择注册中心的类型: +首先要在 `conf/config.yaml` 文件中增加如下配置,添加不同的服务发现客户端,以便在使用过程中动态选择: ```yaml -apisix: - discovery: eureka +discovery: + eureka: + ... ``` 此名称要与 `apisix/discovery/` 目录中实现对应注册中心的文件名保持一致。 @@ -165,33 +166,35 @@ apisix: 在 `conf/config.yaml` 增加如下格式的配置: ```yaml -eureka: - host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster. - - "http://${usename}:${passowrd}@${eureka_host1}:${eureka_port1}" - - "http://${usename}:${passowrd}@${eureka_host2}:${eureka_port2}" - prefix: "/eureka/" - fetch_interval: 30 # 从 eureka 中拉取数据的时间间隔,默认30秒 - weight: 100 # default weight for node - timeout: - connect: 2000 # 连接 eureka 的超时时间,默认2000ms - send: 2000 # 向 eureka 发送数据的超时时间,默认2000ms - read: 5000 # 从 eureka 读数据的超时时间,默认5000ms +discovery: + eureka: + host: # it's possible to define multiple eureka hosts addresses of the same eureka cluster. + - "http://${usename}:${passowrd}@${eureka_host1}:${eureka_port1}" + - "http://${usename}:${passowrd}@${eureka_host2}:${eureka_port2}" + prefix: "/eureka/" + fetch_interval: 30 # 从 eureka 中拉取数据的时间间隔,默认30秒 + weight: 100 # default weight for node + timeout: + connect: 2000 # 连接 eureka 的超时时间,默认2000ms + send: 2000 # 向 eureka 发送数据的超时时间,默认2000ms + read: 5000 # 从 eureka 读数据的超时时间,默认5000ms ``` -通过 `eureka.host ` 配置 eureka 的服务器地址。 +通过 `discovery.eureka.host ` 配置 eureka 的服务器地址。 如果 eureka 的地址是 `http://127.0.0.1:8761/` ,并且不需要用户名和密码验证的话,配置如下: ```yaml -eureka: - host: - - "http://127.0.0.1:8761" - prefix: "/eureka/" +discovery: + eureka: + host: + - "http://127.0.0.1:8761" + prefix: "/eureka/" ``` ## upstream 配置 -APISIX是通过 `upstream.service_name` 与注册中心的服务名进行关联。下面是将 URL 为 "/user/*" 的请求路由到注册中心名为 "USER-SERVICE" 的服务上例子: +APISIX是通过 `upstream.discovery_type`选择使用的服务发现, `upstream.service_name` 与注册中心的服务名进行关联。下面是将 URL 为 "/user/*" 的请求路由到注册中心名为 "USER-SERVICE" 的服务上例子: ```shell $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d ' @@ -199,7 +202,8 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f "uri": "/user/*", "upstream": { "service_name": "USER-SERVICE", - "type": "roundrobin" + "type": "roundrobin", + "discovery_type": "eureka" } }' @@ -210,7 +214,7 @@ Transfer-Encoding: chunked Connection: keep-alive Server: APISIX web server -{"node":{"value":{"uri":"\/user\/*","upstream": {"service_name": "USER-SERVICE", "type": "roundrobin"}},"createdIndex":61925,"key":"\/apisix\/routes\/1","modifiedIndex":61925},"action":"create"} +{"node":{"value":{"uri":"\/user\/*","upstream": {"service_name": "USER-SERVICE", "type": "roundrobin", "discovery_type": "eureka"}},"createdIndex":61925,"key":"\/apisix\/routes\/1","modifiedIndex":61925},"action":"create"} ``` 因为上游的接口 URL 可能会有冲突,通常会在网关通过前缀来进行区分: @@ -226,7 +230,8 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f } "upstream": { "service_name": "A-SERVICE", - "type": "roundrobin" + "type": "roundrobin", + "discovery_type": "eureka" } }' @@ -240,7 +245,8 @@ $ curl http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f } "upstream": { "service_name": "B-SERVICE", - "type": "roundrobin" + "type": "roundrobin", + "discovery_type": "eureka" } }' ``` diff --git a/t/discovery/eureka.t b/t/discovery/eureka.t index 3801e7f..f5241e7 100644 --- a/t/discovery/eureka.t +++ b/t/discovery/eureka.t @@ -26,18 +26,17 @@ apisix: node_listen: 1984 config_center: yaml enable_admin: false - discovery: eureka - -eureka: - host: - - "http://127.0.0.1:8761" - prefix: "/eureka/" - fetch_interval: 10 - weight: 80 - timeout: - connect: 1500 - send: 1500 - read: 1500 +discovery: + eureka: + host: + - "http://127.0.0.1:8761" + prefix: "/eureka/" + fetch_interval: 10 + weight: 80 + timeout: + connect: 1500 + send: 1500 + read: 1500 _EOC_ run_tests(); @@ -52,6 +51,7 @@ routes: uri: /eureka/* upstream: service_name: APISIX-EUREKA + discovery_type: eureka type: roundrobin #END @@ -78,6 +78,7 @@ routes: uri: /eureka/* upstream: service_name: APISIX-EUREKA-DEMO + discovery_type: eureka type: roundrobin #END @@ -100,6 +101,7 @@ routes: regex_uri: ["^/eureka-test/(.*)", "/${1}"] upstream: service_name: APISIX-EUREKA + discovery_type: eureka type: roundrobin #END