PowerDotNet平台化软件架构设计与实现系列(04):服务治理平台

系统和系统之间,少不了数据的互联互通。随着微服务的流行,一个系统内的不同应用进行互联互通也是常态。

PowerDotNet的服务治理平台发源于早期的个人项目Power.Apix。这个项目借鉴了工作过的公司的服务治理方案,站在巨人的肩膀上,一步一步从无到有模仿设计和实现。

一开始,Power.Apix被设计用于基于XML的Web服务通信,因为Web服务在当时是主流通信方式,朴素版本大概长下面这个样子:

服务端:

服务端只要加上ApixClazz、ApixMethod两个特性,一个Apix服务就完美实现了:

客户端:

后来,随着个人开发经验的丰富,陆陆续续添加了更多的序列化协议的支持,而初期设计的仅支持Web服务通信则被改的面目全非。

Power.Apix支持常见的HTTP方法:

Power.Apix支持不同的序列化方式:

通过抓包分析,可以发现Power.Apix已经支持自定义请求头:

十年磨一剑。经过多年优化和改进,负载均衡、限流、黑白名单、日志等功能逐步迭代开发出来,在以HTTP协议为主流的文本协议框架里,Power.Apix现在已经非常完善和强大,尤其是部署非常方便,在一般请求应答业务场景下,完全可以取代.NET Remoting、WebApi、WebService和WCF。

简单介绍完Power.Apix,下面再来说说本文的主题服务治理平台。

我们常见的传统的RPC接口调用,比如WebApi、WebService、WCF、.NET Remoting、gRPC、Thrift、Hessian、自定义RPC协议(比如个人项目Power.Apix)等,如果是少量调用,还好说。但是一旦接口多起来,系统关系复杂,就容易造成各种混乱。

我已经不止看到一个系统,不论是.Net还是Java开发的应用,都要配置各种接口服务地址,调用的地方各种拼接接口名称,各种HTTP帮助类,看着就不够优雅,可以说都是demo水平。咩哈哈,就是demo水平。

PowerDotNet在借鉴主流微服务治理框架和协议(包括但不限于ZooKeeper、Consul、Nacos、HSF、ETCD、Dubbo、Spring Cloud、Ocelot、Hessian、gRPC、Thrift、Kubernates等)的基础上,独立开发出了一套简洁高效的服务治理平台。

在一个基于服务(SOA)的分布式环境中,常见的消息交互模式(Message Exchange Pattern,即MEP)主要包括如下几种:

1、RequestReply:经典请求应答模型,客户端发起一个请求后会等待一个响应才可以进行下一次请求

2、Oneway:客户端发起一个请求后不等待一个响应

3、Duplex:双向通信,客户端发起请求得到服务端一个响应,服务端再回调通知客户端一个响应,HTTP和TCP协议会有不同的实现逻辑

4、Streaming:客户端发起一个或多个请求 , 等待一个或多个响应

PowerDotNet目前完美支持RequestReply这一经典交互模式,毕竟来源于web环境下以HTTP为文本协议的Power.Apix,当然简单的Oneway模式只需要简单改造不多的框架代码就可以支持。

PowerDotNet早期自研了一套基于ZooKeeper的注册中心Power.RegistryCenter,后来逐步改造放弃ZooKeeper为默认注册中心,因为曾经某厂的ZooKeeper由于磁盘IO太高,导致ZooKeeper集群挂掉,进而导致重大生产事故。

CAP理论上来说,ZooKeeper保证的是CP(一致性和分区容错性),然而注册中心尤其是服务发现功能更应该保证的是AP(可用性和分区容错性),可用性比数据一致性更加重要 。

PowerDotNet最新自研的注册中心遵循AP原则,高可用性基于DB、本地缓存、Redis和ETCD,且Redis和ETCD都是可插拔的插件式可选模式,用户选择更多,同时还能保证高可用。

从服务拉取方式和性能上来看,PowerDotNet的注册中心采用的是客户端(Power.RegistryCenter.Client)拉取模式,客户端定时(默认间隔30秒,这个参考了SpringCloud的Eureka)主动拉取(续租)服务端(Power.RegistryCenter.Server)服务并缓存在本地,而早期的ZooKeeper客户端监听服务列表变化,服务变更主动推送给消费者,在规模较大的服务集群上,很容易产生性能问题。

复用是PowerDotNet设计的时候优先考虑的主题。针对不同协议的RPC接口,PowerDotNet设计的时候做了各种妥协,现已经完美支持WebApi、WebService、WCF(支持常见的几种绑定协议,包括BasicHttpBinding、WSHttpBinding、NetTcpBinding等)、.NET Remoting(支持HTTP和TCP协议)、gRPC、Thrift、Hessian、IHttpHandler(ASPX、ASHX、个人项目Power.Apix)的互联互通。

PowerDotNet还有一个后续开发计划PowerDotNetCore,以支持.NetCore下的主要通信协议,目前.NetCore2.1、.NetCore3.0和.NET5下的WebApi已经完美支持,其他等我有空慢慢来开发实现,咩哈哈,都是脏活累活苦活呀。后续再考虑开发支持和Java接口互通。

仅需要遵循一点点PowerDotNet规范,接口生产者可以快速开发API接口,接口消费者利用PowerDotNet自动生成工具,快速生成接口消费代理类,就和调用本地方法一样容易。

如果你的系统里有不同的RPC接口形式需要互联互通,比如WebApi调用WCF,WebService调用WebApi......或者相同的RPC形式互调,PowerDotNet都能够让你以一种优雅愉悦的方式实现接口调用。

环境准备

1、(必须).Net Framework4.5+

2、(必须)关系型数据库MySQL或SqlServer或PostgreSQL或MariaDB四选一

3、(可选)分布式键值存储ETCD

4、(可选)分布式缓存Redis或Memcached二选一

5、(可选)消息队列RabbitMQ或MSMQ 二选一

6、(可选)ElasticSearch

一、服务注册

支持自动注册和人工注册,自动注册类、字段等相关元数据。

 二、服务发现

通过心跳程序,定时(默认5秒间隔)发送心跳来判断应用服务器的可用状态(保活)。心跳程序健壮可靠,可以通过配置中心对心跳参数进行动态设置。

配合服务治理客户端工具,可以自动发现新接入或者心跳停止的服务器,自动实现服务发现。

如何保证心跳程序健壮可靠?PowerDotNet的心跳设计包含了两种常见模式:推模式和拉模式。

推模式指应用服务器主动发送心跳至平台注册中心,这是常规的心跳检查方式。

拉模式指平台注册中心通过定时任务主动对应用服务器发起心跳接口调用,间接触发应用服务器心跳程序自检。

通过推模式和拉模式进行心跳检查,可以最大程度减少某些应用(如寄宿在web容器上的服务,如果你熟悉IIS的话,应该知道IIS Worker Process默认会配置Idle Timeout 为20分钟,即该进程在20分钟内没有任何请求的话就会自动结束)自动“休眠”导致心跳线程不能被唤醒而造成的心跳判断错误。

当然拉模式是一种可关停的备选方案,通常推模式的心跳程序可以支持绝大多数应用服务的心跳检查。

这篇文章中,我们可以从【应用部署管理】看到应用部署服务器的心跳情况,从而为实现基于心跳的服务发现打下基础。

服务发现的关键部分是注册中心,注册中心提供注册和查询(发现)功能。

服务发现主要有两种发现模式:客户端发现和服务端发现。

客户端发现模式要求客户端负责查询注册中心,获取服务提供者的列表信息,使用负载均衡算法选择一个合适的服务提供者,发起接口调用请求。

服务端发现模式则要求客户端每次都请求注册中心,由注册中心内部使用负载均衡算法选择一个合适的服务提供者,并将请求转发至该服务提供者。

这两种模式都有自己的优点和缺点,PowerDotNet可以通过开关动态实现两种发现模式的自由切换,就问你灵不灵活吧?

目前业界开源的有Nacos、Netflix Eureka、ETCD、Consul和Zookeeper等注册中心方案,PowerDotNet在参考了这些现有成熟方案之后,结合实践经验,选择了支持ETCD。PowerDotNet服务注册和发现,在使用ETCD的基础上进行了优化和改进,通过开关动态控制,使得ETCD只是一种可插拔的服务治理实现。

ETCD的管理在下一篇文章中单独讲讲。

三、服务消费

支持服务白名单和服务消费特殊逻辑配置。

白名单里的接口可以直接消费。

服务消费可以对接口进行配置Token和签名校验特殊逻辑。

四、黑名单

通过配置黑名单规则,按配置实现动态黑名单功能。

 五、灰度发布

通过灰度发布规则,实现灰度发布功能。

六、API网关

主流的RPC框架在服务消费的时候,都有完备的客户端工具,支持服务鉴权、负载均衡、黑白名单、限流等功能。

PowerDotNet也优先实现了客户端形式的服务调用,支持主流功能。

但是,很多种场景下,都不得不考虑加入API网关,把API网关放到各种API服务的最前端,并且让API网关变成由各应用所发起的每个请求的入口。这样做可以明显的简化客户端调用服务端API。

PowerDotNet实现了一个通用简易功能的API网关,也支持服务鉴权、负载均衡、限流、黑白名单、灰度发布等功能,比客户端调用API接口功能还略丰富,并且可以继续扩展新功能。

PowerDotNet自研的负载均衡组件,包含随机、加权随机、轮询、加权轮询和客户端IP哈希五种算法,并提供了负载均衡接口,可按需动态扩展。

PowerDotNet自研的限流组件,通过配置中心动态调整开关,在注册中心通过后台管理系统动态配置,支持根据IP地址或者应用名称进行限流,并提供了接口,可按需动态扩展。

PowerDotNet负载均衡和限流组件,已经运用在网关和客户端,是通用的可扩展组件。

API网关支持对内外网开放,也可以同时部署两套,对内和对外的分开。在对外的网关上,建议对被消费的接口勾选加上验证签名和Token功能,网关会自动处理判断客户端请求是否合法。

七、常用工具

1、服务测试

为了更好的测试待发布的部署服务器,可以通过选择或者输入来动态切换,非常灵活

2、代理类生成和下载

早期的远程服务调用好像一直是比较啰嗦且费力不讨好的,要么配置繁琐,要么引入很多依赖,要么IDE装啥插件,要么调用代码demo水平的写法(尤其各种HTTP工具类,烦不胜烦),总之调用别人的服务整体感觉就是乏味无趣。

PowerDotNet设计的远程服务调用,目标是“无配置,无引用,全自动”,截至目前来看,可以说出色的达到了这一目标。

咩哈哈,通过PowerDotNet调用RPC服务,只需要一个方法RemoteApiClient.Invoke<TRequest, TResponse>(methodName, request);完成调用,有点太简洁太优雅了。

 3、API文档管理

只要每个独立API自动集成Swagger,通过管理后台都能自动识别查看。

 也自动支持.Net Core应用:

上面这些工具对快速开发和排查问题非常有帮助。

 

参考:

https://www.consul.io/

https://dubbo.apache.org/zh/

https://zookeeper.apache.org/

https://github.com/alibaba/nacos

https://nacos.io/zh-cn/index.html

https://blog.csdn.net/marine2010/article/details/5401366

https://spring.io/projects/spring-cloud

http://hessian.caucho.com/

http://doc.oschina.net/grpc/

https://thrift.apache.org/

https://etcd.io/

https://kubernetes.io/

https://dapr.io/

https://github.com/ThreeMammals/Ocelot

 

posted on 2021-11-21 23:33  JeffWong  阅读(1058)  评论(4编辑  收藏  举报