1、首先远程服务调用有三种模式:同步、异步 Future、异步 Callback 三种调用模型,正常的都是同步调用,调用的时候阻塞当前线程,异步一般只会在特殊的情景下有用。
2、全局配置:所有服务的配置应该是需要在一个全局配置中心配置(zookeeper集群)的,而不是写死在代码里面,避免出现问题还需要修改代码、重启所有机器。尤其是流量控制、接口降级、重试次数等。
3、接口的重试:远程调用接口一般由于网络问题等问题经常会出现异常,这时候往往可以需要重试一下,但是不是所有的接口都需要重试,比如由于处理时间过长导致超时异常,其实只是处理慢了点而已,已经处理了,这时候再重试会有问题的,所以一般建议update、insert类型的接口就不要重试了,或者接口能保证幂等。(像由于接口异常问题导致的数据不一致可以通过mq实现重试,在消费mq时保证幂等。这样能最大限度的保证数据一致性)
4、服务节点的自动注册和发现:一个分布式的rpc框架肯定缺不了服务的注册与发现,注册中心有很多种实现方式,一般采用zookeeper集群来实现。
5、负载均衡:client端对server的调用负载均衡能规避短板效应,常见的负载均衡算法有轮询、随机、最少调用、一致hash等加权的算法。
6、熔断:这个功能也是一个分布式框架必须要有的。比如服务方法级的熔断可以使得client端在短时间内发现该方法大量异常就会直接抛出异常,避免继续给server端增加压力,防止级联崩溃。合适的设置消费方服务方法熔断,既可以保护服务提供方,避免其已经处于不健康状态下时继续给压。也可以避免消费方应用大量线程因等待服务方结果返回被阻塞(在同步调用下),有效的保护服务消费方自身。还有一种是服务节点级的熔断,比如发现该节点cpu打满、节点不可用,直接将本节点踢出集群,这样client在负载均衡调用时会忽略这个节点。
7、流量控制:分client段的流量控制和server端的流量控制。
服务端的流量控制:避免请求超过系统设计的承受能力,防止服务崩溃,应该设置一个合理的阀值,超过阀值的请求可以被快速拒绝。在服务提供方维护一个线程池,该线程池负责服务接口的执行,线程池有个任务队列,一但队列满了,直接拒绝服务。
消费方的流量控制:消费方可针对某个服务设置并发阀值,也可用线程池去维护,当并发量超过该阀值时则无法执行,合理的设置消费方的并发阀值不仅能有效的保护服务方,而且也能避免消费方大量线程因等待服务方结果返回被阻塞(在同步调用下),有效的保护服务消费方自身。
8、服务路由:client端的集群调用server端的那个集群是可以配置的,集群隔离也能有效的防止某个clinet的并发暴增导致的关键链路雪崩。在server端设置服务路由也能有效的控制所有client端调用的集群,集群隔离,保护自身。
9、服务治理及监控:trace监控也是很重要的,作为大型分布式系统,一个api接口的server方可能级联高达数十个,那么监控同一链路不同层级server的性能和参数日志就很重要,也可以依赖对此设置异常告警。
延伸一个问题,在超大型分布式系统里,为了更高的响应速度,可能会部署多机房,这时候很多业务的数据库架构为了性能就会出现跨zone拒绝写入的问题,这时候就很需要服务路由去解决找到正确的机房。