简介:Pixiu 是基于 Dubbogo 的云原生、高性能、可扩大的微服务 API 网关。作为一款网关产品,Pixiu 帮忙用户轻松创立、公布、保护、监控和爱护任意规模的 API,承受和解决成千上万个并发 API 调用,包含流量治理、CORS 反对、受权和访问控制、限度、监控,以及 API 版本治理。
Pixiu 是什么
在答复 Pixiu 是什么之前,咱们简略解释一下 Dubbo 是什么。Dubbo 是一个开源的高性能 RPC 框架,有着丰盛的服务治理能力以及优良的扩大能力。Dubbo 更扩大出 Dubbo-go,为用户提供了 Golang 的 Dubbo 解决方案,买通了两种语言之间的隔膜,使 Dubbo 更加贴近云原生。
Dubbo-go 作为 Golang 服务,实现与 Dubbo 服务之间的互相调用。然而,在日常应用场景中,用户往往有把 Dubbo 服务以 RESTful 格调向外裸露的需要同时也要兼顾外部 Dubbo 调用。为了解决这种场景,作为 Dubbo API 网关的 Pixiu (中文: 貔貅,曾用名 dubbo-go-proxy) 便应运而生。之所以采纳 Pixiu 这个名称,是因为 Java 同类产品 Zuul 的意象是一个东方怪兽,Pixiu 作为一个国产产品,就用了咱们中国的一个相似的神兽貔貅作为项目名称。也同时表白了 Dubbo 社区心愿扩大出一整套云原生生态链的信心。
目前 Dubbo 多语言生态,倒退最好的天然是 Java,其次是 Golang,其余语言都差强人意。dubbo-go-pixiu 我的项目是一个基于 dubbo-go 倒退起来的我的项目,目前接口协议层反对的是七层的 HTTP 申请调用,打算在将来的 0.5 版本中反对 gRPC 申请调用,其另外一个使命是作为一种新的 dubbo 多语言解决方案。
为什么应用 Pixiu
Pixiu 是基于 Dubbogo 的云原生、高性能、可扩大的微服务 API 网关。作为一款网关产品,Pixiu 帮忙用户轻松创立、公布、保护、监控和爱护任意规模的 API,承受和解决成千上万个并发 API 调用,包含流量治理、CORS 反对、受权和访问控制、限度、监控,以及 API 版本治理。除此以外,作为 Dubbo 的衍生产品,Pixiu 能够帮忙 Dubbo 用户进行协定转换,实现跨零碎、跨协定的服务能力互通。
Pixiu 的整体设计恪守以下准则:
High performance: 高吞吐量以及毫秒级的延时。
可扩大: 通过 go-plugin,用户能够依据本人的需要延展 Pixiu 的性能。
简略可用: 用户通过大量配置,即可上线。
Pixiu 的个性及外围性能
为 RESTful API 和 Dubbo API 提供反对
非 RESTful 格调的 API 和 Dubbo 协定的服务往往须要批改才能够以 RESTful API 格调对外开放。Pixiu 提供协定转换性能,通过 Pixiu,开发者能够将本人的 HTTP API 或 Dubbo API 通过配置,以 RESTful API 格调对外开放。v0.2.1 版本已反对基于泛化调用的 HTTP 至 Dubbo 的协定转换以及 HTTP 协定的转发。在后续的版本,社区将会减少对 gRPC 和 http2 协定的反对。
面向用户的配置形式
个别的网关的配置往往繁琐且简单。Pixiu,指标作为一款易用的网关产品,在设计上领有三层配置层级,Gateway 层全局配置,API resource 层配置以及 HTTP verbs 办法层配置。通过三个不同层级的配置,既能够实现深度的定制,亦反对对立的默认配置;同时,反对本地的配置文件,亦可应用对立配置服务器。另外,还提供控制台模块,通过控制台模块,反对配置的热更新。Pixiu 配套配套的控制台界面也在同步开发中。
通用性能的集成
重试、熔断、流量管制、访问控制等通用性能不再须要在每个后端服务上反复实现。应用 Pixiu,通过配置 filter,开发者能够进行全局的管制,亦能够依据 API 配置各自的规定。因而开发者能够专一于业务逻辑和服务,而不是将工夫用在保护基础设施上。
可扩大
不同的应用场景有着各自独特的需要。为满足不同用户的定制化需要,Pixiu 应用了插件模式。开发者能够通过编写 go plugin,将本身特有的业务逻辑以 filter 模式内嵌至 Pixiu 网关中,实现诸如企业登录鉴权等性能。
图 1: Pixiu 外围性能列表
Pixiu 的架构设计
图 2: Pixiu 架构
貔貅: 即 dubbo-go-pixiu,由四个次要模块:Listener、Router、Filters 和 Clients 组成;
Dubbo Cluster: Dubbo 服务所在集群,蕴含一个或多个 Dubbo Services;
Other Cluster: Dubbo 以外的服务所在集群,现反对 HTTP 服务,将来将拓展反对 gRPC 等其余服务;
Registry Center: 注册核心,保护每个业务服务的调用地址信息;
Metadata Center: 元数据中心,保护每个业务服务的配置信息以及存储 Pixiu 自身的配置信息。
作为 Dubbo 所衍生的 API 网关,Pixiu 应用 Golang 搭建,次要因为: 1. Golang 的 G-M-P,net poller 等个性使 Golang 非常适合构建 IO 密集型利用;2. 应用 Golang 能够间接引入 Dubbo-go 中的一些组建,简化开发。
整个 Pixiu 大抵能够拆分为四个次要模块:Listener、Router、Filters 和 Client。
1、Listener
在 Pixiu 中,Listener 代表内部能够拜访 Pixiu 的形式。通过配置指定协定类型,地址,端口等属性,裸露 Gateway。现阶段暂反对 HTTP 协定,将来将会退出 gRPC。
listeners:
- name: "net/http"
address:
socket_address:
protocol_type: "HTTP"
address: "0.0.0.0"
port: 8888
config:
idle_timeout: 5s
read_timeout: 5s
write_timeout: 5s
2、Router
Router 是 Pixiu 的路由组件。依据配置文件,Pixiu 将对外裸露的 URLs 以树的局势存储于内存中,当申请到了 router 组件时,即会依据 URL 及 HTTP 办法查找到对应的后端服务及其 API 配置,并将信息封装于申请中,为后续 filter,及 client 的调用提供足够的内容。
现阶段,Router 提供以下性能:
- 反对申请一对一转发路由配置或 wildcard 路由配置。
- 反对 HTTP 申请的转发到后端 HTTP 服务。
- 反对 HTTP 申请转化为 dubbo 泛化调用申请。
3、Filters
Filter 是 Pixiu 实现额定性能及其扩展性的次要组件。其实现相似于 Dubbo-go 中的 filter,依据配置中 filter 的指定,生成调用链,从而在调用后端服务前,将各 filter 中的逻辑运行一遍,实现节流,日志等性能。
用户如果须要客制化的 filter,可通过编写 go-plugin 实现。在配置中,可通过相似如下配置,加载 .so 文件,并在 API config 中指定应用的 plugin group,plugin name 实现。
pluginFilePath: ""
pluginsGroup:
- groupName: "group1"
plugins:
- name: "rate limit"
version: "0.0.1"
priority: 1000
externalLookupName: "ExternalPluginRateLimit"
- name: "access"
version: "0.0.1"
priority: 1000
externalLookupName: "ExternalPluginAccess"
- groupName: "group2"
plugins:
- name: "blacklist"
version: "0.0.1"
priority: 1000
externalLookupName: "ExternalPluginBlackList"
4、Client
Client 负责调用具体服务。现阶段,Pixiu 反对 HTTP 与 Dubbo 的后端服务。社区将逐步减少 gRPC 等其余 Client 以满足不同的协定。
HTTP client 的实现绝对简略,依据 Router 中获取的后端服务信息,通过 Golang 官网包 net/http 生成申请并调用。
Dubbo client 的实现比照 HTTP client 会略微简单,其根底为 Dubbo 服务的泛化调用。泛化调用技术是 Dubbo 提供的一个很根底的性能只须要晓得调用的办法名、参数类型和返回值类型,即可发动服务调用。客户端对服务端的泛化调用既能够通过注册核心发现服务,也能够直连服务端,实现对服务的动静调用。
如上面代码所示,Pixiu 通过动静配置 referenceConfig,而后通过 GetRPCService 生成 Dubbo 的 Generic Client(泛化调用客户端)进行下一步的调用。
referenceConfig := dg.NewReferenceConfig(irequest.Interface, context.TODO())
referenceConfig.InterfaceName = irequest.Interface
referenceConfig.Cluster = constant.DEFAULT_CLUSTER
var registers []string
for k := range dgCfg.Registries {registers = append(registers, k)
}
referenceConfig.Registry = strings.Join(registers, ",")
if len(irequest.DubboBackendConfig.Protocol) == 0 {referenceConfig.Protocol = dubbo.DUBBO} else {referenceConfig.Protocol = irequest.DubboBackendConfig.Protocol}
referenceConfig.Version = irequest.DubboBackendConfig.Version
referenceConfig.Group = irequest.Group
referenceConfig.Generic = true
if len(irequest.DubboBackendConfig.Retries) == 0 {referenceConfig.Retries = "3"} else {referenceConfig.Retries = irequest.DubboBackendConfig.Retries}
dc.lock.Lock()
defer dc.lock.Unlock()
referenceConfig.GenericLoad(key)
clientService := referenceConfig.GetRPCService().(*dg.GenericService)
实际上,在泛化调用的客户端中,理论执行泛化调用的关键步骤是 Dubbo-go 中的 generic_filter (如下代码片段)。在调用 generic_filter 的 Invoke 时,约定 invocation 参数列表第一个为办法名,第二个为参数类型列表,第三个为参数值列表。generic_filter 将用户申请的参数值列表转化为对立格局的 map(代码中的 struct2MapAll),将类(golang 中为 struct)的正反序列化操作变成 map 的正反序列化操作。这使得无需 POJO 形容通过硬编码注入 hessain 库,从而实现 Dubbo 服务的泛化调用。
func (ef *GenericFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {if invocation.MethodName() == constant.GENERIC && len(invocation.Arguments()) == 3 {oldArguments := invocation.Arguments()
if oldParams, ok := oldArguments[2].([]interface{}); ok {newParams := make([]hessian.Object, 0, len(oldParams))
for i := range oldParams {newParams = append(newParams, hessian.Object(struct2MapAll(oldParams[i])))
}
newArguments := []interface{}{oldArguments[0],
oldArguments[1],
newParams,
}
newInvocation := invocation2.NewRPCInvocation(invocation.MethodName(), newArguments, invocation.Attachments())
newInvocation.SetReply(invocation.Reply())
return invoker.Invoke(ctx, newInvocation)
}
}
return invoker.Invoke(ctx, invocation)
}
总结
通过下面的四个模块以及注册核心的简略介绍不难发现,当申请通过 listener 被 Pixiu 接管后,申请被传入 router 中。router 依据接口的配置,从原申请中找到指标后端服务连同相干 API 配置下发到 filter 组件。filter 组件依据原申请、API 配置等信息程序执行,最终申请达到 client,通过 client 调用后端服务。
Pixiu 的将来
图 3: Pixiu 迭代里程碑
Pixiu 作为网关产品外,其衍生我的项目也会在咱们的将来打算中,次要目标是提供更好的可用性。例如,因为 Golang 语言不足原生的注解,因而 Dubbo-go 须要通过配置文件形式生成服务的元数据写入注册核心。开课啦教育公司相干同学写了一个扫描代码的工具 _https://github.com/jack15083/…,在每个 RPC 服务办法前加上对应的正文,从而在服务启动前通过扫描正文生成元数据。Pixiu 也打算在将来的版本上通过提供 package,容许服务通过正文借助 _https://github.com/MarcGrol/g… _生成 API 配置并注册到 Pixiu 上。
Pixiu 目前的定位是一个七层协定网关,其最后版本是被定义成一个 Dubbo 的服务网关。作为云时代的产品,Pixiu 的倒退方向必然是面向云原生的。当初的版本为 0.2.1, 曾经实现根本的 Dubbo/Http 服务代理和局部的网关通用性能。目前正在开发中的 0.4 及其后续版本反对 gRPC 和 Spring Cloud 服务调用,后续还将提供 MQ 服务反对。另外,社区将持续优化配置形式,升高用户的应用难度,持续优化官网的 filter,使 Pixiu 能够在官网层面实现更多的网关通用性能。
在将来的一年内,社区打算反对 xDS API,将 Pixiu 演变为 Dubbo mesh 的 sidecar。其最终目标就是:在现有的 dubbo mesh 状态中演化出 Proxy Service Mesh 状态。基于这个状态,Js、Python、PHP、Ruby 和 Perl 等脚本语言程序除了播种 dubbo mesh 原有的技术红利之外,大概率还能播种性能上的晋升。
Pixiu 在 Dubbo Mesh 中的终极目标是:把东西向和南北向数据面流量逐渐对立 Pixiu 中的同时,让它逐渐具备 Application Runtime 的能力,作为 Dubbo 多语言生态的要害解决方案。
冯振宇,Apache Dubbo Committer,目前负责管理香港一家消费品公司的 IT 部门整个团队。2020 年夏天 偶尔看到了介绍 dubbogo 的文章后退出了 dubbogo 社区,目前在主导 Pixiu 0.4.0 版本的开发。
原文链接
本文为阿里云原创内容,未经容许不得转载。