支持从nacos(已实现),eureka(已实现)等注册中心同步到apisix(已实现)和kong(已实现) 等网关,后续将支持自定义插件,支持用户自己用golang实现支持类似携程阿波罗注册中心,etcd注册中心,consul注册中心等插件,以及spring gateway等网关插件的高扩展性
本项目不再维护,后续功能改进修复,将改为 python 重写的项目 https://github.com/anjia0532/discovery-syncer-python
从 releases 下载最新的对应系统的二进制文件
discovery-syncer-windows-amd64.exe --help
usage: discovery-syncer-windows-amd64.exe [<flags>]
Flags:
-h, --help Show context-sensitive help (also try --help-long and --help-man).
-p, --web.listen-address=":8080"
The address to listen on for web interface.
-c, --config.file="config.yml"
Path to configuration file.
docker run anjia0532/discovery-syncer:v2.0.0
特别的,-c
支持配置远端http[s]的地址,比如读取静态资源的,比如读取nacos的
-c http://xxxxx/nacos/v1/cs/configs?tenant=public&group=DEFAULT_GROUP&dataId=discovery-syncer.yaml
,便于管理
# 是否启用 pprof
# 通过 http://ip:port/debug/pprof/ 访问
enable-pprof: false
logger:
level: debug # debug,info,error
logger: console # console vs file
log-file: syncer.log # The file name of the logger output, does not exist automatically
date-slice: y # Cut the document by date, support "y" (year), "m" (month), "d" (day), "h" (hour), default "y".
# 注册中心,map形式
discovery-servers:
# nacos1 是注册中心的名字,可以随便定义,但是不能重复
nacos1:
# 类型,目前仅支持 nacos和eureka
type: nacos
# 默认,如果注册中心没有返回权重时,添加的默认权重
weight: 100
# 注册中心的url前缀
prefix: /nacos/v1/
# 注册中心的连接地址,注意最后不能带/
host: "http://nacos-server:8858"
eureka1:
type: eureka
weight: 100
prefix: /eureka/
# 对于basic认证,可以这么写
host: "http://admin:admin@eureka-server:8761"
# 网关,map形式
gateway-servers:
# 网关名字,可以随便写,但是不能重复
apisix1:
# 网关类型,目前支持apisix和kong
type: apisix
# 管理端host,注意最后不能有/
admin-url: http://apisix-server:9080
# 管理端uri前缀
prefix: /apisix/admin/
# 特别的扩展参数,在config里用key:value形式添加
config:
X-API-KEY: xxxxx
# apisix admin api 目前2.15.x 和 3.x 差异较大 详见 https://apisix.apache.org/zh/docs/apisix/next/upgrade-guide-from-2.15.x-to-3.0.0/
# 默认是v2,如果是3.x的,请改成v3
version: v2
kong1:
type: kong
admin-url: http://kong-server:8001
prefix: /upstreams/
# 同步任务,列表形式
targets:
# 注意同一个注册中心,但是有多个租户(类似nacos的命名空间)时,不需要创建多个相同的注册中心
# 只需要创建多个targets,然后改config的扩展参数即可
# 第一个任务
# 注册中心,来源
- discovery: nacos1
# 网关,目标
gateway: apisix1
# 是否启用
enabled: false
# 拉取间隔,具体支持表达式,详见 https://github.com/robfig/cron
fetch-interval: "@every 10s"
# 默认是把能拉倒的注册中心的服务都拉过来,有些不需要的,则进行排除,支持正则
exclude-service: [ 'ex*','test' ]
# 同步到网关的upstream的名字的前缀,便于管理
upstream-prefix: nacos1
# 本次同步唯一key,为空则是discovery-gateway
name: nacos1-apisix1
# 对于health检查时,超过限定秒数的,认为是失联状态,默认是10秒
maximum-interval-sec: 20
# 扩展参数
config:
# nacos 的groupName
groupName: DEFAULT_GROUP
# nacos的 namespace
namespaceId: test
# 创建到apisix 的upstream的默认模板,具体支持的模板语法,自行搜索 golang text/template
template: |
{
"id": "{{.Name}}",
"timeout": {
"connect": 30,
"send": 30,
"read": 30
},
"name": "{{.Name}}",
"nodes": {{.Nodes}},
"type":"roundrobin",
"desc": "auto sync by https://github.com/anjia0532/discovery-syncer"
}
- discovery: eureka1
gateway: kong1
enabled: false
fetch-interval: "@every 5s"
maximum-interval-sec: 10
config:
template: |
{
"name": "{{.Name}}",
"algorithm": "round-robin",
"hash_on": "none",
"hash_fallback": "none",
"hash_on_cookie_path": "/",
"slots": 10000,
"healthchecks": {
"passive": {
"healthy": {
"http_statuses": [200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301, 302, 303, 304, 305, 306, 307, 308],
"successes": 0
},
"type": "http",
"unhealthy": {
"http_statuses": [429, 500, 503],
"timeouts": 0,
"http_failures": 0,
"tcp_failures": 0
}
},
"active": {
"timeout": 1,
"https_sni": "example.com",
"http_path": "/",
"concurrency": 10,
"https_verify_certificate": true,
"type": "http",
"healthy": {
"http_statuses": [200, 302],
"successes": 0,
"interval": 0
},
"unhealthy": {
"http_statuses": [429, 404, 500, 501, 502, 503, 504, 505],
"timeouts": 0,
"http_failures": 0,
"interval": 0,
"tcp_failures": 0
}
},
"threshold": 0
},
"tags": ["discovery-syncer-auto"]
}
路径 | 返回值 | 用途 |
---|---|---|
GET / |
OK |
服务是否启动 |
GET /-/reload |
OK |
重新加载配置文件,加载成功返回OK,主要是cicd场景或者k8s的configmap reload 场景使用 |
GET /health |
JSON | 判断服务是否健康,可以配合k8s等容器服务的健康检查使用 |
PUT /discovery/{discovery-name} |
OK |
主动下线上线注册中心的服务,配合CI/CD发版业务用 |
GET /gateway-api-to-file/{gateway-name} |
text/plain | 读取网关admin api转换成文件用于备份或者db-less模式 |
POST /migrate/{gateway-name}/to/{gateway-name} |
JSON | 将网关数据迁移(目前仅支持apisix) |
GET /health
的返回值
{
// 一共有几个enabled的同步任务(targets)
"total": 2,
// 正常在跑的有几个
"running": 2,
// 有几个超过 配置文件定义的maximum-interval-sec的检测时间没有运行的,失联的。
"lost": 0,
// 都在跑,状态是OK(http状态码是200),有在跑的,有失联的,状态是WARN(http状态码是200),全部失联,状态是DOWN(http状态码500)
"status": "OK",
// 哪些成功,哪些失败
"details": [
"syncer:a_task,is ok",
"syncer:b-api,is ok"
],
// 运行时长
"uptime": "1m6s"
}
PUT /discovery/{discovery-name}
中的name是注册中心的名字,如果不存在,则返回 Not Found
http status code 是404
body入参
{
// 检索哪个服务下的实例
"serviceName": "",
// 基于注册中心元数据还是基于实例ip来查找
"type": "METADATA/IP",
// 匹配的查询条件,支持正则
"regexpStr": "",
// 匹配的元数据key,如果是ip则不用填
"metadataKey": "",
// 匹配到的将状态改成上线还是下线
"status": "UP/DOWN",
// 其他没匹配的,状态是上线还是下线,ORIGIN保持不变
"otherStatus": "UP/DOWN/ORIGIN",
// 扩展参数
"extData": {
}
}
GET /gateway-api-to-file/{gateway-name}
中的gateway-name是网关的名字,如果不存在,则返回 Not Found
,http status code
是404
如果服务报错,resp body 会返回空字符串,header 中的 syncer-err-msg
会返回具体原因 http status code 是500
如果正常,resp body 会返回转换后的文本内容,syncer-file-location
会返回syncer服务端的路径(
一般是系统临时目录+文件名,例如/tmp/apisix.yaml
), http status
code是200
注意
精力有限,目前仅实现了apisix的admin api转yaml功能,kong的未实现,有需要的,欢迎提PR贡献代码或者提issues来反馈
-
目前的同步任务是串行的,如果待同步的量比较大,或者同步时间窗口设置的特别小的情况下,会导致挤压
-
不支持自定义同步插件,不利于自行扩展
-
同步机制目前是基于定时轮询,效率比较低,有待优化,比如增加缓存开关,上游注册中心与缓存比对没有差异的情况下,不去拉取/变更下游网关的upstream信息,或者看看注册中心支不支持变动主动通知机制等。
This module is licensed under the BSD license.
Copyright (C) 2017-, by AnJia anjia0532@gmail.com.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.