diff --git a/apisix/discovery/consul/init.lua b/apisix/discovery/consul/init.lua index 4d3c0e46be25..0411f1516902 100644 --- a/apisix/discovery/consul/init.lua +++ b/apisix/discovery/consul/init.lua @@ -21,6 +21,7 @@ local core_sleep = require("apisix.core.utils").sleep local resty_consul = require('resty.consul') local http = require('resty.http') local util = require("apisix.cli.util") +local discovery_utils = require("apisix.utils.discovery") local ipairs = ipairs local error = error local ngx = ngx @@ -78,8 +79,7 @@ function _M.all_nodes() return all_services end - -function _M.nodes(service_name) +function _M.nodes(service_name, discovery_args) if not all_services then log.error("all_services is nil, failed to fetch nodes for : ", service_name) return @@ -87,6 +87,10 @@ function _M.nodes(service_name) local resp_list = all_services[service_name] + if discovery_args and discovery_args.metadata_match then + resp_list = discovery_utils.nodes_metadata_match(resp_list, discovery_args.metadata_match) + end + if not resp_list then log.error("fetch nodes failed by ", service_name, ", return default service") return default_service and {default_service} @@ -98,7 +102,6 @@ function _M.nodes(service_name) return resp_list end - local function update_all_services(consul_server_url, up_services) -- clean old unused data local old_services = consul_services[consul_server_url] or {} @@ -511,11 +514,17 @@ function _M.connect(premature, consul_server, retry_delay) local nodes = up_services[service_name] local nodes_uniq = {} for _, node in ipairs(result.body) do - if not node.Service then + local service = node.Service + if not service then goto CONTINUE end - local svc_address, svc_port = node.Service.Address, node.Service.Port + local svc_address = service.Address + local svc_port = service.Port + local metadata = service.Meta + if type(metadata) ~= "table" then + metadata = nil + end -- Handle nil or 0 port case - default to 80 for HTTP services if not svc_port or svc_port == 0 then svc_port = 80 @@ -532,7 +541,8 @@ function _M.connect(premature, consul_server, retry_delay) core.table.insert(nodes, { host = svc_address, port = tonumber(svc_port), - weight = default_weight, + weight = metadata and tonumber(metadata.weight) or default_weight, + metadata = metadata }) nodes_uniq[service_id] = true end diff --git a/apisix/schema_def.lua b/apisix/schema_def.lua index d8b62088476c..61a5f3e1fef0 100644 --- a/apisix/schema_def.lua +++ b/apisix/schema_def.lua @@ -488,6 +488,18 @@ local upstream_schema = { description = "group name", type = "string", }, + metadata_match = { + description = "metadata for filtering service instances", + type = "object", + additionalProperties = { + type = "array", + items = { + description = "candidate metadata value", + type = "string", + }, + uniqueItems = true, + } + }, } }, pass_host = { diff --git a/apisix/utils/discovery.lua b/apisix/utils/discovery.lua new file mode 100644 index 000000000000..b712e56dac4b --- /dev/null +++ b/apisix/utils/discovery.lua @@ -0,0 +1,55 @@ +-- +-- 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. +-- +local core = require("apisix.core") +local ipairs = ipairs +local pairs = pairs + +local _M = {} + +local function do_metadata_match(inst, filters) + local metadata = inst.metadata or {} + for key, values in pairs(filters) do + local matched = false + for _, value in ipairs(values) do + if metadata[key] == value then + matched = true + break + end + end + if not matched then + return false + end + end + return true +end + +local function nodes_metadata_match(nodes, metadata_match) + if not nodes then + return nil + end + + local result = {} + for _, node in ipairs(nodes) do + if do_metadata_match(node, metadata_match) then + core.table.insert(result, node) + end + end + return result +end +_M.nodes_metadata_match = nodes_metadata_match + +return _M diff --git a/docs/en/latest/discovery/consul.md b/docs/en/latest/discovery/consul.md index fd6758bc9abb..dd3e2e56d397 100644 --- a/docs/en/latest/discovery/consul.md +++ b/docs/en/latest/discovery/consul.md @@ -232,6 +232,61 @@ $ curl http://127.0.0.1:9180/apisix/admin/stream_routes/1 -H "X-API-KEY: $admin_ }' ``` +### discovery_args + +| Name | Type | Requirement | Default | Valid | Description | +|----------------| ------ | ----------- | ------- | ----- | ------------------------------------------------------------ | +| metadata_match | object | optional | {} | | Filter service instances by metadata using containment matching | + +#### Metadata filtering + +APISIX supports filtering service instances based on metadata. When a route is configured with metadata conditions, only service instances whose metadata matched with roles specified in the route's `metadata_match` configuration will be selected. + +Example: If a service instance has metadata `{lane: "a", env: "prod", version: "1.0"}`, it will match routes configured with metadata `{lane: ["a"]}` or `{lane: ["a", "b"], env: "prod"}`, but not routes configured with `{lane: ["c"]}` or `{lane: "a", region: "us"}`. + +Example of routing a request with metadata filtering: + +```shell +$ curl http://127.0.0.1:9180/apisix/admin/routes/5 -H "X-API-KEY: $admin_key" -X PUT -i -d ' +{ + "uri": "/nacosWithMetadata/*", + "upstream": { + "service_name": "APISIX-NACOS", + "type": "roundrobin", + "discovery_type": "nacos", + "discovery_args": { + "metadata": { + "version": ["v1", "v2"] + } + } + } +}' +``` + +This route will only route traffic to service instances that have the metadata field `version` set to `v1` or `v2`. + +For multiple metadata criteria: + +```shell +$ curl http://127.0.0.1:9180/apisix/admin/routes/6 -H "X-API-KEY: $admin_key" -X PUT -i -d ' +{ + "uri": "/nacosWithMultipleMetadata/*", + "upstream": { + "service_name": "APISIX-NACOS", + "type": "roundrobin", + "discovery_type": "nacos", + "discovery_args": { + "metadata": { + "lane": ["a"], + "env": ["prod"] + } + } + } +}' +``` + +This route will only route traffic to service instances that have both `lane: "a"` and `env: "prod"` in their metadata. + You could find more usage in the `apisix/t/discovery/stream/consul.t` file. ## Debugging API diff --git a/docs/zh/latest/config.json b/docs/zh/latest/config.json index f7c9ebd4d258..825fc678b6d1 100644 --- a/docs/zh/latest/config.json +++ b/docs/zh/latest/config.json @@ -281,6 +281,7 @@ "items": [ "discovery", "discovery/dns", + "discovery/consul", "discovery/nacos", "discovery/eureka", "discovery/control-plane-service-discovery", diff --git a/docs/zh/latest/discovery/consul.md b/docs/zh/latest/discovery/consul.md new file mode 100644 index 000000000000..0a56776ed93a --- /dev/null +++ b/docs/zh/latest/discovery/consul.md @@ -0,0 +1,393 @@ +--- +title: consul +--- + + + +## 概述 + +APACHE APISIX 支持使用 [Consul](https://developer.hashicorp.com/consul) 作为服务发现。 + +## 服务发现客户端配置 + +### Consul 配置 + +首先,我们需要在 `conf/config.yaml` 中添加如下配置: + +```yaml +discovery: + consul: + servers: # 确保这些 Consul 服务器中的服务名是唯一的 + - "http://127.0.0.1:8500" # `http://127.0.0.1:8500` 和 `http://127.0.0.1:8600` 是不同的集群 + - "http://127.0.0.1:8600" # 默认跳过的服务名是 `consul` + token: "..." # 如果 Consul 启用了 ACL 访问控制,需要指定 token + skip_services: # 如果需要跳过某些服务 + - "service_a" + timeout: + connect: 1000 # 默认 2000 毫秒 + read: 1000 # 默认 2000 毫秒 + wait: 60 # 默认 60 秒 + weight: 1 # 默认 1 + fetch_interval: 5 # 默认 3 秒,仅在 keepalive 为 false 时生效 + keepalive: true # 默认 true,采用长轮询方式查询 Consul 服务器 + sort_type: "origin" # 默认 origin + default_service: # 当未命中时可以定义默认服务 + host: "127.0.0.1" + port: 20999 + metadata: + fail_timeout: 1 # 默认 1 毫秒 + weight: 1 # 默认 1 + max_fails: 1 # 默认 1 + dump: # 如果需要,在注册节点更新时可写入文件 + path: "logs/consul.dump" + expire: 2592000 # 单位为秒,此处为 30 天 +``` + +你也可以使用默认值进行简化配置: + +```yaml +discovery: + consul: + servers: + - "http://127.0.0.1:8500" +``` + +`keepalive` 有两个可选值: + +* `true`:默认且推荐,使用长轮询方式查询 Consul +* `false`:不推荐,使用短轮询方式查询,可设置 `fetch_interval` 来定义拉取间隔 + +`sort_type` 有四种可选值: + +* `origin`:不排序 +* `host_sort`:按主机排序 +* `port_sort`:按端口排序 +* `combine_sort`:在主机排序的前提下对端口也排序 + +#### 数据转储 + +当我们需要在线 reload `apisix` 时,Consul 模块可能比从 ETCD 加载路由更慢,可能会出现如下日志: + +``` + http_access_phase(): failed to set upstream: no valid upstream node +``` + +因此我们引入了 `dump` 功能。当 reload 时,会优先加载 dump 文件;当 Consul 中注册的节点更新时,会自动将上游节点写入文件。 + +`dump` 支持三个配置项: + +* `path`:转储文件保存路径 + + * 支持相对路径,如:`logs/consul.dump` + * 支持绝对路径,如:`/tmp/consul.dump` + * 确保父目录存在 + * 确保 `apisix` 进程有读写权限,如可在 `conf/config.yaml` 中加入: + +```yaml +nginx_config: # 渲染模板生成 nginx.conf 的配置 + user: root # 指定 worker 进程的运行用户 +``` + +* `load_on_init`,默认值为 `true` + + * 如果为 `true`,在加载 Consul 数据之前尝试读取 dump 文件 + * 如果为 `false`,则忽略 dump 文件 + * 无论为 `true` 还是 `false`,都无需预先准备 dump 文件 +* `expire`:单位为秒,用于避免加载过期 dump 数据 + + * 默认值为 `0`,永不过期 + * 推荐设置为 2592000,即 30 天(3600 × 24 × 30) + +### 注册 HTTP API 服务 + +将节点注册到 Consul: + +```shell +curl -X PUT 'http://127.0.0.1:8500/v1/agent/service/register' \ +-d '{ + "ID": "service_a1", + "Name": "service_a", + "Tags": ["primary", "v1"], + "Address": "127.0.0.1", + "Port": 8000, + "Meta": { + "service_a_version": "4.0" + }, + "EnableTagOverride": false, + "Weights": { + "Passing": 10, + "Warning": 1 + } +}' + +curl -X PUT 'http://127.0.0.1:8500/v1/agent/service/register' \ +-d '{ + "ID": "service_a1", + "Name": "service_a", + "Tags": ["primary", "v1"], + "Address": "127.0.0.1", + "Port": 8002, + "Meta": { + "service_a_version": "4.0" + }, + "EnableTagOverride": false, + "Weights": { + "Passing": 10, + "Warning": 1 + } +}' +``` + +在某些情况下,不同 Consul 服务中可能存在相同服务名。 +为避免混淆,推荐在实践中使用完整的 Consul 键路径作为服务名。 + +### 端口处理 + +当 APISIX 从 Consul 获取服务信息时,端口处理逻辑如下: + +* 如果服务注册中包含有效端口号,则使用该端口 +* 如果端口为 `nil` 或 `0`,则默认使用 HTTP 的 80 端口 + +### Upstream 配置 + +#### L7 + +以下是一个将路径为 "/\*" 的请求路由到名为 "service\_a" 且使用 Consul 作为服务发现的 upstream 的示例: + +```shell +$ curl http://127.0.0.1:9180/apisix/admin/routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d ' +{ + "uri": "/*", + "upstream": { + "service_name": "service_a", + "type": "roundrobin", + "discovery_type": "consul" + } +}' +``` + +响应示例如下: + +```json +{ + "key": "/apisix/routes/1", + "value": { + "uri": "/*", + "priority": 0, + "id": "1", + "upstream": { + "scheme": "http", + "type": "roundrobin", + "hash_on": "vars", + "discovery_type": "consul", + "service_name": "service_a", + "pass_host": "pass" + }, + "create_time": 1669267329, + "status": 1, + "update_time": 1669267329 + } +} +``` + +你可以在 `apisix/t/discovery/consul.t` 文件中找到更多用例。 + +#### L4 + +Consul 服务发现也支持在 L4 中使用,配置方式与 L7 类似。 + +```shell +$ curl http://127.0.0.1:9180/apisix/admin/stream_routes/1 -H "X-API-KEY: $admin_key" -X PUT -i -d ' +{ + "remote_addr": "127.0.0.1", + "upstream": { + "scheme": "tcp", + "service_name": "service_a", + "type": "roundrobin", + "discovery_type": "consul" + } +}' +``` + +### discovery\_args + +| 名称 | 类型 | 是否必需 | 默认值 | 可选值 | 描述 | +| --------------- | ------ | ---- | --- | --- | ------------------- | +| metadata\_match | object | 可选 | {} | | 使用包含匹配的方式按元数据过滤服务实例 | + +#### 元数据过滤 + +APISIX 支持根据元数据过滤服务实例。当路由配置了元数据条件时,只有元数据满足 `metadata_match` 条件的服务实例才会被选中。 + +示例:服务实例的元数据为 `{lane: "a", env: "prod", version: "1.0"}`,则以下配置匹配成功:`{lane: ["a"]}` 或 `{lane: ["a", "b"], env: "prod"}`,但 `{lane: ["c"]}` 或 `{lane: "a", region: "us"}` 则匹配失败。 + +带元数据过滤的路由示例: + +```shell +$ curl http://127.0.0.1:9180/apisix/admin/routes/5 -H "X-API-KEY: $admin_key" -X PUT -i -d ' +{ + "uri": "/nacosWithMetadata/*", + "upstream": { + "service_name": "APISIX-NACOS", + "type": "roundrobin", + "discovery_type": "nacos", + "discovery_args": { + "metadata": { + "version": ["v1", "v2"] + } + } + } +}' +``` + +仅路由到带 `version` 字段且值为 `v1` 或 `v2` 的服务实例。 + +多条件元数据过滤示例: + +```shell +$ curl http://127.0.0.1:9180/apisix/admin/routes/6 -H "X-API-KEY: $admin_key" -X PUT -i -d ' +{ + "uri": "/nacosWithMultipleMetadata/*", + "upstream": { + "service_name": "APISIX-NACOS", + "type": "roundrobin", + "discovery_type": "nacos", + "discovery_args": { + "metadata": { + "lane": ["a"], + "env": ["prod"] + } + } + } +}' +``` + +只有同时包含 `lane: "a"` 和 `env: "prod"` 的实例才会被匹配。 + +更多用法请参考 `apisix/t/discovery/stream/consul.t` 文件。 + +## 调试接口 + +提供了调试用的控制接口。 + +### 内存转储接口 + +```shell +GET /v1/discovery/consul/dump +``` + +示例: + +```shell +# curl http://127.0.0.1:9090/v1/discovery/consul/dump | jq +{ + "config": { + "fetch_interval": 3, + "timeout": { + "wait": 60, + "connect": 6000, + "read": 6000 + }, + "weight": 1, + "servers": [ + "http://172.19.5.30:8500", + "http://172.19.5.31:8500" + ], + "keepalive": true, + "default_service": { + "host": "172.19.5.11", + "port": 8899, + "metadata": { + "fail_timeout": 1, + "weight": 1, + "max_fails": 1 + } + }, + "skip_services": [ + "service_d" + ] + }, + "services": { + "service_a": [ + { + "host": "127.0.0.1", + "port": 30513, + "weight": 1 + }, + { + "host": "127.0.0.1", + "port": 30514, + "weight": 1 + } + ], + "service_b": [ + { + "host": "172.19.5.51", + "port": 50051, + "weight": 1 + } + ], + "service_c": [ + { + "host": "127.0.0.1", + "port": 30511, + "weight": 1 + }, + { + "host": "127.0.0.1", + "port": 30512, + "weight": 1 + } + ] + } +} +``` + +### 查看转储文件接口 + +还提供了查看转储文件的控制接口。未来可能添加更多调试 API。 + +```shell +GET /v1/discovery/consul/show_dump_file +``` + +示例: + +```shell +curl http://127.0.0.1:9090/v1/discovery/consul/show_dump_file | jq +{ + "services": { + "service_a": [ + { + "host": "172.19.5.12", + "port": 8000, + "weight": 120 + }, + { + "host": "172.19.5.13", + "port": 8000, + "weight": 120 + } + ] + }, + "expire": 0, + "last_update": 1615877468 +} +``` diff --git a/t/discovery/consul.t b/t/discovery/consul.t index 9ec87202118e..91b84b387984 100644 --- a/t/discovery/consul.t +++ b/t/discovery/consul.t @@ -781,3 +781,71 @@ location /sleep { qr// ] --- ignore_error_log + + + +=== TEST 16: test metadata_match with consul discovery +--- yaml_config eval: $::yaml_config +--- apisix_yaml +routes: + - + uri: /* + upstream: + service_name: service-a + type: roundrobin + discovery_type: consul + discovery_args: + metadata_match: + version: + - v2 + - v3 +#END +--- config +location /v1/agent { + proxy_pass http://127.0.0.1:8500; +} +location /sleep { + content_by_lua_block { + local args = ngx.req.get_uri_args() + local sec = args.sec or "2" + ngx.sleep(tonumber(sec)) + ngx.say("ok") + } +} +--- timeout: 5 +--- pipelined_requests eval +[ + "PUT /v1/agent/service/register\n" . "{\"ID\":\"service-a1\",\"Name\":\"service-a\",\"Address\":\"127.0.0.1\",\"Port\":30511,\"Meta\":{\"service_b_version\":\"4.1\",\"version\":\"v1\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /v1/agent/service/register\n" . "{\"ID\":\"service-a2\",\"Name\":\"service-a\",\"Address\":\"127.0.0.1\",\"Port\":30512,\"Meta\":{\"service_b_version\":\"4.1\",\"version\":\"v2\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /v1/agent/service/register\n" . "{\"ID\":\"service-a3\",\"Name\":\"service-a\",\"Address\":\"127.0.0.1\",\"Port\":30513,\"Meta\":{\"service_b_version\":\"4.1\",\"version\":\"v3\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /v1/agent/service/register\n" . "{\"ID\":\"service-a4\",\"Name\":\"service-a\",\"Address\":\"127.0.0.1\",\"Port\":30514,\"Meta\":{\"service_b_version\":\"4.1\",\"version\":\"v4\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "GET /sleep", + + "GET /hello?run1", + "GET /hello?run2", + "GET /hello?run3", + + "PUT /v1/agent/service/deregister/service-a1", + "PUT /v1/agent/service/deregister/service-a2", + "PUT /v1/agent/service/deregister/service-a3", + "PUT /v1/agent/service/deregister/service-a4", +] +--- response_body_like eval +[ + qr//, + qr//, + qr//, + qr//, + qr/ok\n/, + + qr/[2-3]/, + qr/[2-3]/, + qr/[2-3]/, + + qr//, + qr//, + qr//, + qr// +] +--- no_error_log +[error] diff --git a/t/discovery/consul2.t b/t/discovery/consul2.t index 16f2f630d08b..0cf8fb9bc989 100644 --- a/t/discovery/consul2.t +++ b/t/discovery/consul2.t @@ -145,7 +145,7 @@ location /consul3 { "PUT /consul2/deregister/service_a2", "PUT /consul3/deregister/service_a1", "PUT /consul3/deregister/service_a2", - "PUT /consul1/register\n" . "{\"ID\":\"service_a1\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30511,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", + "PUT /consul1/register\n" . "{\"ID\":\"service_a1\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30511,\"Meta\":{\"service_a_version\":\"4.0\", \"weight\":\"100\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", "PUT /consul1/register\n" . "{\"ID\":\"service_a2\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"127.0.0.1\",\"Port\":30512,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", "PUT /consul1/register\n" . "{\"ID\":\"service_a3\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"localhost\",\"Port\":30511,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", "PUT /consul1/register\n" . "{\"ID\":\"service_a4\",\"Name\":\"service_a\",\"Tags\":[\"primary\",\"v1\"],\"Address\":\"localhost\",\"Port\":30512,\"Meta\":{\"service_a_version\":\"4.0\"},\"EnableTagOverride\":false,\"Weights\":{\"Passing\":10,\"Warning\":1}}", @@ -189,7 +189,7 @@ discovery: --- request GET /t --- response_body -{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"localhost","port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","port":80,"weight":1}]} +{"service_a":[{"host":"127.0.0.1","metadata":{"service_a_version":"4.0","weight":"100"},"port":30511,"weight":100},{"host":"127.0.0.1","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30511,"weight":1},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","metadata":{"service_version":"1.0"},"port":80,"weight":1}]} @@ -223,7 +223,7 @@ discovery: --- request GET /t --- response_body -{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"localhost","port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","port":80,"weight":1}]} +{"service_a":[{"host":"127.0.0.1","metadata":{"service_a_version":"4.0","weight":"100"},"port":30511,"weight":100},{"host":"127.0.0.1","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30511,"weight":1},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","metadata":{"service_version":"1.0"},"port":80,"weight":1}]} @@ -257,7 +257,7 @@ discovery: --- request GET /t --- response_body -{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","port":80,"weight":1}]} +{"service_a":[{"host":"127.0.0.1","metadata":{"service_a_version":"4.0","weight":"100"},"port":30511,"weight":100},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30511,"weight":1},{"host":"127.0.0.1","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","metadata":{"service_version":"1.0"},"port":80,"weight":1}]} @@ -291,7 +291,7 @@ discovery: --- request GET /t --- response_body -{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1},{"host":"127.0.0.1","port":30512,"weight":1},{"host":"localhost","port":30511,"weight":1},{"host":"localhost","port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","port":80,"weight":1}]} +{"service_a":[{"host":"127.0.0.1","metadata":{"service_a_version":"4.0","weight":"100"},"port":30511,"weight":100},{"host":"127.0.0.1","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30511,"weight":1},{"host":"localhost","metadata":{"service_a_version":"4.0"},"port":30512,"weight":1}],"service_no_port":[{"host":"127.0.0.1","metadata":{"service_version":"1.0"},"port":80,"weight":1}]} diff --git a/t/discovery/consul_dump.t b/t/discovery/consul_dump.t index 9cb24a3c175b..be0ac8e03501 100644 --- a/t/discovery/consul_dump.t +++ b/t/discovery/consul_dump.t @@ -95,7 +95,7 @@ discovery: --- request GET /t --- response_body -{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1}],"service_b":[{"host":"127.0.0.1","port":8002,"weight":1}]} +{"service_a":[{"host":"127.0.0.1","metadata":{"service_a_version":"4.0"},"port":30511,"weight":1}],"service_b":[{"host":"127.0.0.1","metadata":{"service_b_version":"4.1"},"port":8002,"weight":1}]} @@ -450,7 +450,7 @@ discovery: --- request GET /bonjour --- response_body -{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1}],"service_b":[{"host":"127.0.0.1","port":30517,"weight":1}]} +{"service_a":[{"host":"127.0.0.1","metadata":{"service_a_version":"4.0"},"port":30511,"weight":1}],"service_b":[{"host":"127.0.0.1","metadata":{"service_b_version":"4.1"},"port":30517,"weight":1}]} @@ -508,4 +508,4 @@ discovery: --- request GET /t --- response_body -{"service_a":[{"host":"127.0.0.1","port":30511,"weight":1}]} +{"service_a":[{"host":"127.0.0.1","metadata":{"service_a_version":"4.0"},"port":30511,"weight":1}]}