1. 服务启动时将自身的一些信息,比如服务名、IP、端口等信息上报到注册中心;各个服务与注册中心使用一定机制(例如心跳)通信,如果注册中心与服务长时间无法通信,就会注销该实例;当服务下线时,会删除注册中心的实例信息;
  2. 网关会准实时地从注册中心获取服务实例信息;
  3. 当用户通过网关请求服务时,网关从注册中心获取的实例列表中选择一个进行代理;

常见的注册中心:Eureka, Etcd, Consul, Nacos, Zookeeper等

APISIX 要扩展注册中心其实是件非常容易的事情,其基本步骤如下:

  1. 在 目录中添加注册中心客户端的实现;
  2. 实现用于初始化的 _M.init_worker() 函数以及用于获取服务实例节点列表的 _M.nodes(service_name) 函数;
  3. 将注册中心数据转换为 APISIX 格式的数据;

实现 eureka.lua

首先在 apisix/discovery/ 目录中添加 eureka.lua;

然后在 eureka.lua 实现用于初始化的 init_worker 函数以及用于获取服务实例节点列表的 nodes 函数即可:

Eureka 与 APISIX 之间数据转换逻辑

  1. {
  2. "applications": {
  3. "application": [
  4. {
  5. "name": "USER-SERVICE", # 服务名称
  6. "instance": [
  7. {
  8. "instanceId": "192.168.1.100:8761",
  9. "hostName": "192.168.1.100",
  10. "app": "USER-SERVICE", # 服务名称
  11. "ipAddr": "192.168.1.100", # 实例 IP 地址
  12. "status": "UP", # 状态
  13. "overriddenStatus": "UNKNOWN", # 覆盖状态
  14. "$": 8761, # 端口
  15. "@enabled": "true" # 开始端口
  16. },
  17. "securePort": {
  18. "$": 443,
  19. "@enabled": "false"
  20. },
  21. "management.port": "8761",
  22. "weight": 100 # 权重,需要通过 spring boot 应用的 eureka.instance.metadata-map.weight 进行配置
  23. },
  24. "homePageUrl": "http://192.168.1.100:8761/",
  25. "statusPageUrl": "http://192.168.1.100:8761/actuator/info",
  26. "healthCheckUrl": "http://192.168.1.100:8761/actuator/health",
  27. ... ...
  28. }
  29. ]
  30. }
  31. ]
  32. }
  33. }

解析 instance 数据步骤:

  1. 首先要选择状态为 “UP” 的实例: overriddenStatus 值不为 “UNKNOWN” 以 overriddenStatus 为准,否则以 status 的值为准;
  2. IP 地址:以 ipAddr 的值为 IP; 并且必须是 IPv4 或 IPv6 格式的;
  3. 端口:端口取值规则是,如果 port[“@enabled”] 等于 “true” 那么使用 port[“$”] 的值;如果 securePort[“@enabled”] 等于 “true” 那么使用 securePort[“$”] 的值;
  4. 权重:权重取值顺序是,先判断 metadata.weight 是否有值,如果没有,则取配置中的 eureka.weight 的值, 如果还没有,则取默认值100

这个例子转成 APISIX nodes 的结果如下:

首先要在 conf/config.yaml 文件中增加如下配置,以选择注册中心的类型:

  1. apisix:
  2. discovery: eureka

此名称要与 apisix/discovery/ 目录中实现对应注册中心的文件名保持一致。

现已支持注册中心有:Eureka 。

通过 eureka.host 配置 eureka 的服务器地址。

如果 eureka 的地址是 http://127.0.0.1:8761/ ,并且不需要用户名和密码验证的话,配置如下:

  1. eureka:
  2. - "http://127.0.0.1:8761"
  3. prefix: "/eureka/"

APISIX是通过 upstream.service_name 与注册中心的服务名进行关联。下面是将 URL 为 “/user/*“ 的请求路由到注册中心名为 “USER-SERVICE” 的服务上例子:

因为上游的接口 URL 可能会有冲突,通常会在网关通过前缀来进行区分:

  1. $ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
  2. {
  3. "plugins": {
  4. "proxy-rewrite" : {
  5. regex_uri: ["^/a/(.*)", "/${1}"]
  6. }
  7. }
  8. "upstream": {
  9. "service_name": "A-SERVICE",
  10. "type": "roundrobin"
  11. }
  12. }'
  13. $ curl http://127.0.0.1:9080/apisix/admin/routes/2 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
  14. {
  15. "uri": "/b/*",
  16. "plugins": {
  17. "proxy-rewrite" : {
  18. regex_uri: ["^/b/(.*)", "/${1}"]
  19. }
  20. }
  21. "upstream": {
  22. "service_name": "B-SERVICE",
  23. "type": "roundrobin"
  24. }

假如 A-SERVICE 和 B-SERVICE 都提供了一个 /test 的接口,通过上面的配置,可以通过 /a/test 访问 A-SERVICE 的 /test 接口,通过 /b/test 访问 B-SERVICE 的 /test 接口。