一、分布式和微服务架构的定义
分布式应用场景涵盖的面非常广,我理解的部分:
- 不同进程之间的互相通信,
- 不同主机的分布式对象之间调用,
- 用于大数据存储的分布式文件系统,
- 用于网络之间相互识别的命名服务,
- 集群中计算或存储的无中心对等模型,
- 分布式事务,
- 数据副本在分布式环境中的复制,
- 云计算服务,
- 音视频在网络中的点播和传输
- ....
微服务架构的目的是对原来过于大而重的云应用服务进行解耦,手段是进行比较合理的业务模块拆解,拆解的粒度往往由架构师掌握,实现细粒度的服务,服务在云端形成分布式状态。
那么微服务就具有了分布式的一些应用场景,比如:不同主机的分布式对象之间调用,以前EJB用RMI(远程方法调用),现在微服务常用RPC(远程过程调用);再比如:用于网络之间相互识别的命名服务,以前EJB是JNDI命名服务,现在SpringCloud的Euraka用于微服务的注册和发现,也是分布式是命名服务。
如何通俗地理解「分布式系统」,它解决了哪些问题,有什么优缺点?
上面是我另外一个回答,里面比较详细地描述了历史上过去EJB和Spring的比较,也是分布式与单体应用的比较。那时候EJB代表分布式服务,而spring代表单体服务。
上面的图简单的描绘了一种最简单的单体服务向微服务拆解的过程。当然微服务面临的挑战不仅仅这么简单,这只是微服务的一种比较初始的状态。
二、分布式和微服务这两者解决了什么问题
分布式是计算、服务、存储在网络中互相交流与协作的形式和状态
分布式到底解决了什么?
上图就是典型的分布式计算,一个大文件被切分成四份,MapReduce分成四个任务(进程),然后在同一主机不同进程,或不同主机上进行数据处理,最终再通过网络汇聚到一个合并任务。那么这个时候到分布式就是任务并行,解决了单任务的效率问题。
上图是个典型的分布式状态协调管理图,是Hadoop HDFS集群的HA高可用架构,主副两个Namonode节点,必须活着一个,当判断主的挂了,必须让副的顶上去,这个时候,三个ZK(zookeeper)组成的集群就是作为主副节点的协调者,通过ZKFC进程实现对Namoenode节点的心跳监控和切换命令下发。
另外三个Journalnode节点形成的集群又是namonode分布式状态数据保存的地方,当主namonode挂了,所有的状态必须快速的恢复到副namenode的上面,所以Journalnode必须持续同步状态,满足hdfs集群状态的快速恢复
那么分布式中非常关键的一个应用场景——集群,上述的Hadoop hdfs集群,就需要有一个或几个角色(zookeeper,Journalnode),作为集群状态的协调者和管理者。有时候这种状态管理是对等的(GlusterFS),有时候这种状态管理是集中的(Hadoop就是这样)。
微服务又解决了什么问题呢?
如果这时候在提微服务的分布式优势,就不是目的,而是手段了。微服务只是借助了分布式架构,达到了自己的目的。所以微服务不是基础技术架构的问题,而是上层应用的架构问题。
上面的例子是个简单的互联网医疗服务单体应用,这时候问诊、药品、订单、即时消息都是互联网医疗最核心的业务,信息推送目的是将互联网医疗平台的各类信息进行互联网信息服务平台的推送、发布和交流,达到自我推广的目的。
可恰恰信息推送服务的更新程度很高,因为需要对外连接的互联网服务平台情况复杂,也会有新的服务平台纳入到模块范围,那么作为单体应用就存在这样一个部署问题,每次更新一个新的信息推送功能,就要整体服务重新部署一次,那么这种影响对于核心服务就造成了很大的困扰,这时候的患者、医生、医院的业务影响都是大规模的。
再看看微服务架构,如果将信息推送服务作为单独的微服务存在,其他微服务只是将需要推送到互联网服务平台的内容进行远程调用即可,甚至用消息中心的方式,打包成消息,实现消息事件驱动,让对外发布服务的部署不会干预到其他核心服务,使得整体平台因为部署发布而造成的影响降到最低。这种方式是不是看起来就舒服多了,非常利于部署、发布,甚至增强了整体系统的鲁棒性。
当然微服务解决的问题还有很多,团队分工的细粒度、迭代速度的提升、更易于小范围重构,利于持续化集成(devops)等等,就不一一具体描述了,只把它很有特点的部分拿出来理解一下。
三、这些架构带来的利弊
分布式对应的是就是单机,其优点上节描述了一些,就不赘述了,缺点也很大
部署不简单,运维不简单
网络瓶颈和故障会有重要的影响,
节点若失效,就要有察觉和热替换机制,
一致性问题,例如分布式事务一直是世界性难题,
不仅要考虑均衡负载,更要考虑均衡负载的效果。
数据进行分布式存储,在有些对等模式下还要考虑数据倾斜问题。
微服务除了分布式存储缺点6之外,上述前5个缺点基本上都完美的继承了。
四、利用不当所带来的技术债务
说说微服务设计不当的麻烦问题吧
(1)微服务解耦后,会将一些业务程序从原来数据库查询的方式,转变成远程对象调用,这个过程我在原来的回答中提过,这是反人性的。形成复杂度和需要约定的接口都带来了比SQL查询更大的工作量。而且更反人性的方式就是数据库也跟着微服务进行分库,到底哪些数据需要冗余,哪些数据还能保持数据库范式,基本都能把高程们烦死。
(2)经验欠缺的微服务架构师,容易将微服务切得太细,假如一个单体若被切分成一千个微服务,而且微服务之间用到了远程对象序列化和反序列化,那么这就成了死穴!因为一旦一个微服务的实体对象进行了调整,那么有多少个关联的微服务被污染了,就要不断定位其他微服务的依赖关系并重新发布,这种工作量已经超出了本该解决业务问题的工作量。
因此微服务的划分一定要注意,而且RPC之间的对象传递尽量用简单、松散的结构来做。微服务划分的程度根据业务不同而粒度不同,有种约定是一个微服务进行大的重构,需要一周的时间,做为微服务粒度标准。
五、项目直接使用微服务架构, 是基于对未来的考虑?
微服务架构的考虑,不应该是对未来的考虑,而是对过去单体式应用出现问题后的一种架构重构,从第一节中的图可以看到其重构过程,在互联网医疗的例子中微服务的重构进一步趋向于消息驱动、事件驱动。
从以往实施微服务的经验教训中,我总结出来的经验,如果是新项目的架构师,可以先选择单体应用,然后根据业务发展一点点迭代重构到微服务上来,即便过程中微服务的架构不那么纯粹,甚至单体应用和微服务很长一段时间共存,也要慎重从新的项目上直接去设计微服务。
因为谁也不是算命先生,能估算到自己业务系统会在哪一天,哪个层面,哪个范围就一定需要微服务化解耦。只有系统运行快到那个阶段了,才能让架构师更容易做到合理的微服务化决策。当然了,也有人会有疑惑,系统设计成单体,谁还有心思继续重构微服务,不如直接做成微服务架构多省事,而我想说的是,若无重构之力行,切勿有微服务之念想。
六、K8s和Spring Cloud有什么区别和联系?
Spring Cloud是贯彻微服务架构的一种具体实现框架,包括了springboot作为微服务的独立运行容器,Euraka作为微服务的注册和发现,zuul服务网关,其他的没怎么用,就不提,其实网关我更喜欢用Openresty。
k8s只是容器的一种编排框架,管理者大量的docker容器,但是现在k8s又不集成docker了,晕得很!
docker作为微服务的容器,为每一个微服务都提供了单独的网络、文件系统、进程管理等基础设施,这样每个微服务的状态、运行日志可以更好的被监控和管理。另外容器让部署过程变得简单,促进了现在流行的devops开发、发布、部署一体的管理模式,微服务的容器化其实是天生一对。
七、结尾
当我们理解清楚分布式下的各种场景是什么的一种存在形式的时候,当我们理解微服务又是一种什么分布式场景的时候,我们就更能清楚的去做好微服务的设计决策。
公众号 "读字节" 大数据(技术、架构、应用)的深度,专业解读