You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by vi...@apache.org on 2020/10/30 12:34:22 UTC

[apisix] branch master updated: feature: support multiple service discovery (#2556)

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 <34...@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