欢迎访问Spring Cloud中国社区

我们致力于成为中国最专业的Spring Boot和Spring Cloud交流社区。推荐使用Github直接登录,欢迎加微信号Software_King进入社区微信交流群。若发现网站bug欢迎反馈!

Spring Cloud生态圈Go语言实现的网关

admin · 21天前 · 737 ·

GoGate

Go语言实现的Spring Cloud网关,目标是性能,即使用更少的资源达到更高的QPS。
GoGate使用FastHttp库收发HTTP请求。
目前已经实现的功能有:

  • 基于Eureka的服务发现、注册
  • 请求路由、路由配置热更新
  • 负载均衡
  • 灰度发布(基于Eureka meta信息里的version字段分配流量)
  • 微服务粒度的QPS控制(有基于内存的令牌桶算法限流和Redis + Lua限流两种可选)
  • 微服务粒度的流量统计(暂时实现为记录日志到/tmp目录下)

初步测试了一下性能,结论如下:

相同的硬件环境、Zuul充分预热且关闭Hystrix的前提下,Go版的网关QPS为Zuul的2.3倍,同时内存占用仅为Zuul的十分之一(600M vs 50M)。而且Go基本上第一波请求就能达到最大QPS, zuul要预热几次才会稳定。更详细的测试近期更新。

流程

arc

服务路由: 根据URL匹配后端微服务

流量控制: 令牌桶算法控制qps

URL重写: 调整向后端服务发请求的URL

转发请求: 负载均衡、按比例分配流量

gogate没有提供默认的Post Filter,可根据需要自己实现相应函数。

构建

Go >= 1.6; 依赖管理工具godep。

clone项目并下载依赖:

  1. cd ${GOPATH}/src/github.com/wanghongfei
  2. git clone https://github.com/wanghongfei/gogate
  3. godep restore

最后构建:

  1. go build github.com/wanghongfei/gogate

使用

可以编译main.go直接生成可执行文件,也可以当一个库来使用。

可以在转发请求之前和之后添加自定义Filter来添加自定义逻辑。

详见examples/usage.go

路由配置

规则:

  • id不为空时,会使用eureka的注册信息查询此服务的地址
  • host不为空时, 会优先使用此字段指定的服务地址, 多个地址用逗号分隔
  • 当请求路径匹配多个prefix时,配置文件中prefix最长的获胜

当路由配置文件发生变动时,访问

  1. GET /_mgr/reload

即可应用新配置。

  1. services:
  2. user-service:
  3. # eureka中的服务名
  4. id: user-service
  5. # 以/user开头的请求, 会被转发到user-service服务中
  6. prefix: /user
  7. # 转发时是否去掉请求前缀, 即/user
  8. strip-prefix: true
  9. # 灰度配置
  10. canary:
  11. -
  12. # 对应eurekai注册信息中元数据(metadata map)中key=version的值
  13. meta: "1.0"
  14. # 流量比重
  15. weight: 3
  16. -
  17. meta: "2.0"
  18. weight: 4
  19. -
  20. # 对应没有metadata的服务
  21. meta: ""
  22. weight: 1
  23. trends-service:
  24. id: trends-service
  25. # 请求路径当匹配多个prefix时, 长的获胜
  26. prefix: /trends
  27. strip-prefix: false
  28. # 设置qps限制, 每秒最多请求数
  29. qps: 1
  30. order-service:
  31. id: order-service
  32. prefix: /order
  33. strip-prefix: false
  34. img-service:
  35. # 如果有host, 则不查注册中心直接使用此地址, 多个地址逗号分隔
  36. host: localhost:4444,localhost:5555
  37. prefix: /img
  38. strip-prefix: false
  39. # 上面都没有匹配到时
  40. common-service:
  41. id: common-service
  42. prefix: /
  43. strip-prefix: false

Eureka配置

eureka.json文件

gogate配置

gogate.yml文件:

  1. version: 1.0
  2. server:
  3. # 向eureka注册自己时使用的服务名
  4. appName: gogate
  5. host: 127.0.0.1
  6. port: 8080
  7. # gateway最大连接数
  8. maxConnection: 1000
  9. # gateway请求后端服务超时时间, 毫秒
  10. timeout: 3000
  11. # eureka配置文件名
  12. eurekaConfigFile: eureka.json
  13. # 路由配置文件名
  14. routeConfigFile: route.yml
  15. traffic:
  16. # 是否开启流量记录功能
  17. enableTrafficRecord: true
  18. # 流量日志文件所在目录
  19. trafficLogDir: /tmp
  20. redis:
  21. # 是否使用redis做限速器
  22. enabled: true
  23. # 目前只支持单实例, 不支持cluster
  24. addr: 127.0.0.1:6379
  25. # 限速器lua代码文件
  26. rateLimiterLua: lua/rate_limiter.lua

限流器

gogate有两个限流器实现, MemoryRateLimiterRedisRateLimiter,通过gogate.yml配置文件里的redis.enabled控制。前者使用令牌桶算法实现,适用于单实例部署的场景;后者基于 Redis + Lua 实现,适用于多实例部署。但有一个限制是目前Redis只支持连接单个实例,不支持cluster。

流量日志

gogate会记录过去1s内各个微服务的请求数据,包括成功请求数和失败请求数,然后写入/tmp/{service-id}_yyyyMMdd.log文件中:

  1. 1527580599228,2,1,user-service
  2. 1527580600230,4,1,user-service
  3. 1527580601228,1,1,user-service

毫秒时间戳,成功请求数,失败请求数,服务名

如果在过去的1s内没有请求, 则不会向日志中写入任何数据。

源码地址:https://github.com/SpringCloud/gogate/