架构设计系列文章,请参见连接。
背景
国内互联网公司在选择微服务体系时有两种成熟的解决方案可以选择:Spring Cloud、Apache Dubbo。正所谓选择越多烦恼越多,公司对于技术体系进行选型时就会有比较大的分歧。
也有开发团队结合两者的优点进行业务的开展工作。使用RPC的方式进行内部关系管理,使用Restful作为接口对外暴露的方式进行。这样可以结合不同的特点进行相关的接口的提供。
这里简单的列出来两种方式的优点:
RPC优点:
- 长链接减少建立连接时的资源消耗。
- 二进制形式传输,传输效率高。
- 序列化、反序列化效率高。
- 不需要认证。
Restful优点:
- 通用负载均衡能力。
- 基于资源的管理。
- 需要认证。
原因
两种方式各自有各自的优点。那么标题中为什么写不推荐使用RPC方式呢?作者本着只有放错位置的技术,没有不对的技术的原则。对RPC在企业级应用中的不足来说明一些问题。
不推荐的原因:
- 耦合问题
刚开始使用Dubbo大家都会很容易的接受Provider和Consumer的jar包方式进行服务的管理工作。而慢慢的逐渐深入使用会逐渐的体会到Dubbo的API JAR包变成了一种约束。这样就非常间接,不明显的将Provider和Consumer绑定在一起。如果其中一方出现问题,就会造成另外一方的一些问题。很难通过中间件对服务间耦合进行拆离。
这个问题非常重要,它会直接导致后面所有的问题。
- 语言锁定
微服务的一个准则就是每个服务可以独立的演进,独立发展。可以通过不同的编程语言对服务进行编写。而Dubbo和类似的RPC实现方式使用Jar包的方式发布接口,那么就只能使用JVM上语言进行Jar的解析与加载工作。导致必须使用相同的语言进行rpc接口的调用。
- 上下文传递
Http是一种无状态服务,那并不代表RPC必须是一种无状态服务。在Http协议通过不断的发展在协议中传递了一些有状态的上下文信息,这样可以为服务提供一些有状态的信息以便在业务处理过程中使用。而RPC是一种更加纯粹的无状态服务,它没有标准化的规范导致不可能形成完善的解决方案。在Dubbo中可以借助多种方式进行上下文的传递工作,不过实现起来比较复杂。其中包括:Dubbo 上下文信息,事件通知,协议扩展
- 版本兼容问题
向下兼容问题对于每个软件来说都是一个非常棘手的问题。一方面我们需要让我们的软件持续的发展,另一方面需要兼容之前的代码。解决这个问题JS上解决的很好,每一个JS的函数没有固定的参数个数,没有固定的参数类型。这样相当于用业务来处理版本的兼容型问题。现在Dubbo上如果需要对接口进行新加或者变更的时候就会发现需要重新发布Dubbo API的Jar包。这样对于Provider和Consumer都是工作负担。使用版本号控制Dubbo API版本号时就得进行多服务实例启动。这个问题在Dubbo中没有很好的解决。兼容性
- 负载均衡就剩下一种方案:客户端负载均衡。
对于负载均衡来说Dubbo直接使用了客户端负载均衡的策略完成,直接摒弃了服务端负载均衡的可能行。这种情况下对于负载均衡的动态控制与动态管理工作就会形成问题。
- 发布过程支撑问题
线上发布一般基于切留的方式进行灰度发布,而对于长链接的Dubbo。不能很好的支撑蓝绿发布,灰度发布方式。
运维能力
- 故障隔离能力:
就现阶段技术而言,没有中很好的方式进行可以进行接口(http和rpc)的故障降级与隔离方式。导致服务中一个接口(http和rpc)发生故障后可能传播到整个服务甚至整个系统中。
- 服务隔离能力:
对于整个系统来说部分业务在docker外,部分服务在docker内时就很难进行处理。一套体系最好在一个注册中心中进行服务组册与发现工作。做服务隔离就非常困难。多注册中心
- 指标监控能力:
指标监控对于线上业务服务来说是不可或缺的内容。但是对于Dubbo来说支持的比较弱。只有几个点完成这个,所以有些鸡肋的感觉。
- 服务检测能力:
每个线上服务都需要不断的检测服务的状态,接口响应情况等。对于使用dubbo或heissian方法的检测几乎不太可能。
总结
RPC是微服务中的一部分,但不是全部。所以,对于作者来说Dubbo是用来处理需要RPC的问题时很好的解决方案。但对于微服务实现来说RPC还是有一些欠缺。
对于以上的问题在阿里内部肯定遇到过,而在开源版本中没有找到只能说阿里没有真正的把内部体系化的技术栈开源出来。而阿里能够开源dubbo并开源了很多配套组件的情况下已经为国内的技术发展做出了很大的贡献。不开源的部分肯定有阿里不开源的原因,不要因为你占领了道德高地而不依不饶的让阿里捐献更多。