Gateway杂谈:Gateway环境的构建和整合

前言

很多朋友问我,Gateway如何使用,有没有文档。在github上有一些文档说明,详细描述了如何构建Gateway,Gateway中的各个概念是什么意思,Gateway能够做些什么,但是这些文档缺乏串联。趁着年前工作不忙,写一篇介绍如何利用Gateway整合已有系统的文章,希望可以帮助更多的人。文章里会虚构一个已经存在的业务系统,以及如何使用Gateway来解决问题和整合。如果你对Gateway还不了解,可以访问:Gateway,文档在docs目录下

已有的业务系统

假设我们有2个业务系统,A和B。A和B两个系统对外提供HTTP服务

环境

业务 地址
A-1 192.168.0.101
A-2 192.168.0.102
B-1 192.168.0.201
B-2 192.168.0.202

搭建Gateway

Gateway分为2部分:apiserver和proxy,其中apiserver负责元数据的管理,proxy是真正的用户入口,可以理解为nginx或者apache的角色,proxy是无状态的,可以scale-out。搭建参考:github

整合

创建Cluster

使用Gateway提供的client编写如下代码:

func createCluster() error {
	c, err := getClient()
	if err != nil {
		return err
	}

	id, err := c.NewClusterBuilder().Name("cluster-A").Loadbalance(metapb.RoundRobin).Commit()
	if err != nil {
		return err
	}

        id, err  = c.NewClusterBuilder().Name("cluster-B").Loadbalance(metapb.RoundRobin).Commit()
	if err != nil {
		return err
	}
	return nil
}

以上代码创建了A和B两个Cluster,分别对应业务A和业务B.

创建Server

server是对应真是的业务服务器,使用Gateway提供的client编写如下代码:

func createServer() error {
	c, err := getClient()
	if err != nil {
		return err
	}

	sb := c.NewServerBuilder()
	// 必选项
	sb.Addr("192.168.0.101").HTTPBackend().MaxQPS(100)

	// 健康检查,可选项
	// 每个10秒钟检查一次,每次检查的超时时间30秒,即30秒后端Server没有返回认为后端不健康
	sb.CheckHTTPCode("/check/path", time.Second*10, time.Second*30)

	// 熔断器,可选项
	// 统计周期1秒钟
	sb.CircuitBreakerCheckPeriod(time.Second)
	// 在Close状态60秒后自动转到Half状态
	sb.CircuitBreakerCloseToHalfTimeout(time.Second * 60)
	// Half状态下,允许10%的流量流入后端
	sb.CircuitBreakerHalfTrafficRate(10)
	// 在Half状态,1秒内有2%的请求失败了,转换到Close状态
	sb.CircuitBreakerHalfToCloseCondition(2)
	// 在Half状态,1秒内有90%的请求成功了,转换到Open状态
	sb.CircuitBreakerHalfToOpenCondition(90)

	id, err := sb.Commit()
	if err != nil {
		return err
	}

	// 把这个server加入到cluster A
	c.AddBind(clusterA, id)
	return nil
}

以上代码创建了一个192.168.0.101的server,然后把这个server和Cluster-A做了绑定。可以继续创建192.168.0.102,192.168.0.201,192.168.0.202三个Server,然后分别和A,B两个Cluster绑定。这样在Gateway的元数据中就存在如下对应关系:

  • ClusterA
    • 192.168.0.101
    • 192.168.0.102
  • ClusterB
    • 192.168.0.201
    • 192.168.0.202

创建API

针对A和B提供的API,在Gateway上创建对应的API。比如:

func createAPI() error {
	c, err := getClient()
	if err != nil {
		return err
	}

	sb := c.NewAPIBuilder()
	// 必选项
	sb.Name("用户API")
	// 设置URL规则,匹配所有开头为/api/user的请求
	sb.MatchURLPattern("/api/user/(.+)")
	// 匹配GET请求
	sb.MatchMethod("GET")
	// 匹配所有请求
	sb.MatchMethod("*")
	// 不启动
	sb.Down()
	// 启用
	sb.UP()
	// 分发到Cluster A
	sb.AddDispatchNode(clusterA)

	// 可选项
	// 匹配所有host,和MatchMethod、MatchURLPattern互斥
	sb.MatchDomain("user.xxx.com")
	// 增加访问黑名单
	sb.AddBlacklist("192.168.0.1", "192.168.1.*", "192.168.*")
	// 增加访问报名单
	sb.AddWhitelist("192.168.3.1", "192.168.3.*", "192.168.*")
	// 移除黑白名单
	sb.RemoveBlacklist("192.168.0.1") // 剩余:"192.168.1.*", "192.168.*"
	sb.RemoveWhitelist("192.168.3.1") // 剩余:"192.168.3.*", "192.168.*"

	// 增加默认值
	sb.DefaultValue([]byte("{\"value\", \"default\"}"))
	// 为默认值增加header
	sb.AddDefaultValueHeader("token", "xxxxx")
	// 为默认值增加Cookie
	sb.AddDefaultValueCookie("sid", "xxxxx")

	id, err := sb.Commit()
	if err != nil {
		return err
	}

	fmt.Printf("api id is: %d", id)
	return nil
}

以上代码创建了一个API,这个API被转发到ClusterA。Gateway会使用ClusterA的负载均衡设置访问ClustreA中的真是服务器,如法炮制,可以创建A系统和B系统中提供的其他API。

为什么使用Gateway

看了上面的介绍,读者可能会提出疑问,这些我用Nginx或者Apache就可以完成大部分功能,为什么需要Gateway。这里还是简单介绍了下Gateway的最近本使用,Gateway还有很多的特性,并且这些都是在运行期你通过访问apiserver可以动态的修改Gateway的行为。这里给出Gateway的一份Features:

  • 流量控制
  • 熔断
  • 负载均衡
  • 服务发现
  • 插件机制
  • 路由
  • API 聚合
  • API 参数校验
  • API 访问控制(黑白名单)
  • API 默认返回值
  • API 定制返回值
  • 后端server的健康检查
  • 使用 fasthttp
  • 开放管理API

更多介绍请访问 github

猜你喜欢

转载自my.oschina.net/u/2244142/blog/1621759