随着现在互联网行业的发展,越来越多的框架、中间件、容器等开源技术不断地涌现,更好地来服务于业务,解决实现业务的问题。然而面对众多的技术选择,我们要如何甄别出适合自己团队业务的技术呢?对于人来说,鞋子过大,可能影响奔跑的速度,鞋子过小,可能影响身体的成长。技术对于业务也是如此的关系。
所以,相对于技术的学习、搭建、使用、运维等技能,我们对技术的甄别选择更是重中之重。那么本文要讲的Dubbox框架,又是如何在众多的服务框架中脱颖而出,被团队选中践行服务之路?
技术为业务而生,架构也为业务而出现。随着业务的发展、用户量的增长,系统数量增多,调用依赖关系也变得复杂,为了确保系统高可用、高并发的要求,系统的架构也从单体时代慢慢迁移至服务SOA时代,根据不同服务对系统资源的要求不同,我们可以更合理的配置系统资源,使系统资源利用率最大化。
平台随着业务的发展从 All in One 环境就可以满足业务需求(以Java来说,可能只是一两个war包就解决了);发展到需要拆分多个应用,并且采用MVC的方式分离前后端,加快开发效率;在发展到服务越来越多,不得不将一些核心或共用的服务拆分出来,提供实时流动监控计算等,其实发展到此阶段,如果服务拆分的足够精细,并且独立运行,这个时候至少可以理解为SOA(Service-Oriented Architecture)架构了。
当迎来服务SOA时代,我们面临要解决的问题会很多,比如:系统的复杂度上升、服务依赖关系、服务性能监控、全链路日志、容灾、断路器、限流等。那么面对这些问题为什么还要做分布式服务呢?因为在未来只有砥砺前行,才能走的更高更远。不过看到这些问题不要气馁,先不管这些问题,让我们一步步来梳理下现存有什么问题,我们要完成什么目标,问题自然会迎刃而解。
根据现在团队的业务系统情况,首先我们要梳理出现存的问题是什么:
- 多种调用传输方式:HTTP方式、WebService方式;
- 服务调用依赖关系:人工记录,查看代码分析;
- 服务调用性能监控:日志记录,人工查看时间;
- 服务与应用紧耦合:服务挂掉,应用无法可用;
- 服务集群负载配置:Nginx配置,存在单点问题;
在去选择技术框架时,技术框架最基本要解决上面现存问题,同时我们也要确认出我们的期望,要达到的目标是什么:
- 支持当前业务需求,这是最最基本的条件;
- 服务避免单点问题,去中心化;
- 服务高可用、高并发,解耦服务依赖;
- 服务通用化,支持异构系统调用服务;
- 服务依赖关系自维护,可视化;
- 服务性能监控自统计,可视化;
- 服务需自带注册、发现、健康检查、负载均衡等特性;
- 开发人员关注度高,上手快,简单轻量,低侵入;
还有最重要一点,这也是往往很多技术人员进入的误区,“对于技术,不要为了使用而使用,用最简单合适的技术实现解决问题才是正道”。架构是服务于业务的,能快速方便的满足业务需求的架构才是好的架构。没有最好的,只有适合自己的。
一谈到服务,可能大家很多听说过SOA、MSA等服务的概念名词,近几年MSA炒的比较火,其实每一个概念的背后都在解决不同的问题。此类名词的最大特点就是 一解释就懂,一问就不知,一讨论就打架。
两者说到底都是对外提供接口的一种架构设计方式。我倒觉得微服务其实就是随着互联网的发展,复杂的平台、业务的出现,导致SOA架构向更细粒度、更通用化程度发展,就成了所谓的微服务了。以这种说法做为根据,我觉得SOA与微服务的区别在于如下几个方面:
- 微服务相比于SOA更加精细,微服务更多的以独立的进程的方式存在,互相之间并无影响;
- 微服务提供的接口方式更加通用化,例如HTTP RESTful方式,各种终端都可以调用,无关语言、平台限制;
- 微服务更倾向于分布式去中心化的部署方式,在互联网业务场景下更适合;
微服务与SOA有很多相同之处。两者都属于典型的、包含松耦合分布式组件的系统结构。在围绕着服务的概念创建架构这一方面,微服务提供了一种更清晰、定义更良好的方式。微服务的原则与敏捷软件开发思想是高度一致的,而它与SOA原则的演化的目标也是相同的,则减少传统的企业服务总线开发的高复杂性。两者之间最关键的区别在于,微服务专注于以自治的方式产生价值。但是两种架构背后的意图是不同的:SOA尝试将应用集成,一般采用中央管理模式来确保各应用能够交互运作。微服务尝试部署新功能,快速有效地扩展开发团队。它着重于分散管理、代码再利用与自动化执行。
功能 | SOA | 微服务 |
---|---|---|
组件大小 | 大块业务逻辑 | 单独任务或小块业务逻辑 |
耦合 | 通常松耦合 | 总是松耦合 |
公司架构 | 任何类型 | 小型、专注于功能交叉的团队 |
管理 | 着重中央管理 | 着重分散管理 |
目标 | 确保应用能够交互操作 | 执行新功能,快速拓展开发团队 |
微服务并不是一种新思想的方法。它更像是一种思想的精炼,一种SOA的精细化演进,并且更好地利用了先进的技术以解决问题,例如容器与自动化等。所以对于我们去选择服务技术框架时,并不是非黑即白,而是针对SOA、MSA两种架构设计同时要考虑到兼容性,对于现有平台情况架构设计,退则守SOA,进则攻MSA,阶段性选择适合的。
现在业界比较成熟的服务框架有很多,比如:Hessian、CXF、Dubbo、Dubbox、Spring Cloud、gRPC、thrift等技术实现,都可以进行远程调用,具体技术实现优劣参考以下分析,这也是具体在技术方案选择过程中的重要依据。
Dubbo 是阿里巴巴公司开源的一个Java高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成。不过,略有遗憾的是,据说在淘宝内部,dubbo由于跟淘宝另一个类似的框架HSF(非开源)有竞争关系,导致dubbo团队已经解散,反到是当当网的扩展版本Dubbox仍在持续发展,墙内开花墙外香。其它的一些知名电商如当当、国美维护了自己的分支或者在dubbo的基础开发,但是官方的库缺乏维护,相关的依赖类比如Spring,Netty还是很老的版本(Spring 3.2.16.RELEASE, netty 3.2.5.Final),倒是有些网友写了升级Spring和Netty的插件。
Dubbox和Dubbo本质上没有区别,名字的含义扩展了Dubbo而已,以下扩展出来的功能,也是选择Dubbox很重要的考察点。
- 支持REST风格远程调用(HTTP + JSON/XML);
- 支持基于Kryo和FST的Java高效序列化实现;
- 支持基于Jackson的JSON序列化;
- 支持基于嵌入式Tomcat的HTTP remoting体系;
- 升级Spring至3.x;
- 升级ZooKeeper客户端;
- 支持完全基于Java代码的Dubbo配置;
Spring Cloud完全基于Spring Boot,是一个非常新的项目,2016年推出1.0的release版本,目前Github上更新速度很快. 虽然Spring Cloud时间最短, 但是相比Dubbo等RPC框架, Spring Cloud提供的全套的分布式系统解决方案。Spring Cloud 为开发者提供了在分布式系统(配置管理,服务发现,熔断,路由,微代理,控制总线,一次性token,全局琐,leader选举,分布式session,集群状态)中快速构建的工具,使用Spring Cloud的开发者可以快速的启动服务或构建应用.它们将在任何分布式环境中工作,包括开发人员自己的笔记本电脑,裸物理机的数据中心,和像Cloud Foundry云管理平台。在未来引领这微服务架构的发展,提供业界标准的一套微服务架构解决方案。
缺点是项目很年轻,很少见到国内业界有人在生产上成套使用,一般都是只有其中一两个组件。相关的技术文档大部分是英文的,案例也相对较少,使用的话需要摸索的时间会长一些。
下图是Spring Cloud和Dubbo对比:
Motan是新浪微博开源的一个Java 框架。它诞生的比较晚,起于2013年,2016年5月开源。Motan 在微博平台中已经广泛应用,每天为数百个服务完成近千亿次的调用。与Dubbo相比,Motan在功能方面并没有那么全面,也没有实现特别多的扩展。用的人比较少,功能和稳定性有待观望。对跨语言调用支持较差,主要支持java。
Hessian采用的是二进制RPC协议,适用于发送二进制数据。但本身也是一个Web Service框架对RPC调用提供支持,功能简单,使用起来也方便。基于Http协议进行传输。通过Servlet提供远程服务。通过Hessain本身提供的API来发起请求。响应端根据Hessian提供的API来接受请求。
Hessian优点:
- 整个jar很小,轻量;
- 配置简单;
- 功能强大,抛开了soap(simple object access protocal 简单对象访问协议)、ejb,采用二进制来传递对象;
rpcx是Go语言生态圈的Dubbo, 比Dubbo更轻量,实现了Dubbo的许多特性,借助于Go语言优秀的并发特性和简洁语法,可以使用较少的代码实现分布式的RPC服务。
gRPC是Google开发的高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。本身它不是分布式的,所以要实现上面的框架的功能需要进一步的开发。
thrift是Apache的一个跨语言的高性能的服务框架,也得到了广泛的应用。
以上RPC框架功能比较:
功能 | Hessian | Montan | rpcx | gRPC | Thrift | Dubbo | Dubbox | Spring Cloud |
---|---|---|---|---|---|---|---|---|
开发语言 | 跨语言 | Java | Go | 跨语言 | 跨语言 | Java | Java | Java |
分布式(服务治理) | × | √ | √ | × | × | √ | √ | √ |
多序列化框架支持 | hessian | √(支持Hessian2、Json,可扩展) | √ | × 只支持protobuf) | ×(thrift格式) | √ | √ | √ |
多种注册中心 | × | √ | √ | × | × | √ | √ | √ |
管理中心 | × | √ | √ | × | × | √ | √ | √ |
跨编程语言 | √ | ×(支持php client和C server) | × | √ | √ | × | × | × |
支持REST | × | × | × | × | × | × | √ | √ |
关注度 | 低 | 中 | 低 | 中 | 中 | 中 | 高 | 中 |
上手难度 | 低 | 低 | 中 | 中 | 中 | 低 | 低 | 中 |
运维成本 | 低 | 中 | 中 | 中 | 低 | 中 | 中 | 中 |
开源机构 | Caucho | Apache | Apache | Alibaba | Dangdang | Apache |
实际场景中的选择
- Spring Cloud : Spring全家桶,用起来很舒服,只有你想不到,没有它做不到。可惜因为发布的比较晚,国内还没出现比较成功的案例,大部分都是试水,不过毕竟有Spring作背书,还是比较看好。
- Dubbox:相对于Dubbo支持了REST,估计是很多公司选择Dubbox的一个重要原因之一,但如果使用Dubbo的RPC调用方式,服务间仍然会存在API强依赖,各有利弊,懂的取舍吧。
- Thrift: 如果你比较高冷,完全可以基于Thrift自己搞一套抽象的自定义框架吧。
- Montan:可能因为出来的比较晚,目前除了新浪微博16年初发布的,
- Hessian:如果是初创公司或系统数量还没有超过5个,推荐选择这个,毕竟在开发速度、运维成本、上手难度等都是比较轻量、简单的,即使在以后迁移至SOA,也是无缝迁移。
- rpcx/gRPC:在服务没有出现严重性能的问题下,或技术栈没有变更的情况下,可能一直不会引入,即使引入也只是小部分模块优化使用。
由于Dubbo是基础框架,其实现的内容对于我们实施微服务架构是否合理,也需要我们根据自身需求去考虑是否要修改,比如Dubbo的服务调用是通过RPC实现的,但是如果仔细拜读过Martin Fowler的microservices一文,其定义的服务间通信是HTTP协议的REST API。那么这两种有何区别呢?
服务提供方与调用方接口依赖方式太强:我们为每个微服务定义了各自的service抽象接口,并通过持续集成发布到私有仓库中,调用方应用对微服务提供的抽象接口存在强依赖关系,因此不论开发、测试、集成环境都需要严格的管理版本依赖,才不会出现服务方与调用方的不一致导致应用无法编译成功等一系列问题,以及这也会直接影响本地开发的环境要求,往往一个依赖很多服务的上层应用,每天都要更新很多代码并install之后才能进行后续的开发。若没有严格的版本管理制度或开发一些自动化工具,这样的依赖关系会成为开发团队的一大噩梦。而REST接口相比RPC更为轻量化,服务提供方和调用方的依赖只是依靠一纸契约,不存在代码级别的强依赖,当然REST接口也有痛点,因为接口定义过轻,很容易导致定义文档与实际实现不一致导致服务集成时的问题,但是该问题很好解决,只需要通过每个服务整合swagger,让每个服务的代码与文档一体化,就能解决。所以在分布式环境下,REST方式的服务依赖要比RPC方式的依赖更为灵活。
服务对平台敏感,难以简单复用:通常我们在提供对外服务时,都会以REST的方式提供出去,这样可以实现跨平台的特点,任何一个语言的调用方都可以根据接口定义来实现。那么在Dubbo中我们要提供REST接口时,不得不实现一层代理,用来将RPC接口转换成REST接口进行对外发布。若我们每个服务本身就以REST接口方式存在,当要对外提供服务时,主要在API网关中配置映射关系和权限控制就可实现服务的复用了。
相信这些痛点也是为什么当当网在dubbox(基于Dubbo的开源扩展)中增加了对REST支持的原因之一。
Dubbo实现了服务治理的基础,但是要完成一个完备的微服务架构,还需要在各环节去扩展和完善以保证集群的健康,以减轻开发、测试以及运维各个环节上增加出来的压力,这样才能让各环节人员真正的专注于业务逻辑。
而Spring Cloud依然发扬了Spring Source整合一切的作风,以标准化的姿态将一些微服务架构的成熟产品与框架揉为一体,并继承了Spring Boot简单配置、快速开发、轻松部署的特点,让原本复杂的架构工作变得相对容易上手一些。所以,如果选择Dubbo请务必在各个环节做好整套解决方案的准备,不然很可能随着服务数量的增长,整个团队都将疲于应付各种架构上不足引起的困难。而如果选择Spring Cloud,相对来说每个环节都已经有了对应的组件支持,可能有些也不一定能满足你所有的需求,但是其活跃的社区与高速的迭代进度也会是你可以依靠的强大后盾。
特性 | 描述 |
---|---|
透明远程调用 | 就像调用本地方法一样调用远程方法;只需简单配置,没有任何API侵入; |
负载均衡机制 | Client端LB,可在内网替代F5等硬件负载均衡器; |
容错重试机制 | 服务Mock数据,重试次数、超时机制等; |
自动注册发现 | 注册中心基于接口名查询服务提 供者的IP地址,并且能够平滑添加或删除服务提供者; |
性能日志监控 | Monitor统计服务的调用次调和调用时间的监控中心; |
服务治理中心 | 路由规则,动态配置,服务降级,访问控制,权重调整,负载均衡,等手动配置。 |
自动治理中心 | 无,比如:熔断限流机制、自动权重调整等; |
支持REST风格远程调用(HTTP + JSON/XML);
支持基于Kryo和FST的Java高效序列化实现;
支持基于Jackson的JSON序列化;
支持基于嵌入式Tomcat的HTTP remoting体系;
升级Spring至3.x;
升级ZooKeeper客户端;
支持完全基于Java代码的Dubbo配置;