一、前言
本次专题笔者主要是介绍微服务相关的技术及其实现原理和部分核心源码解析,并且介绍相关技术之间的关系,以及真正运用到生产环境时应当如何做技术选型。
说明:本专题的demo采用的是Spring Boot 2.1.5.RELEASE,当然也会去穿插说明一些笔者从1.5.x系列升级到2.x系列版本所踩到的坑。另外笔者该专题的所有博文都将会围绕着【是什么】,【为什么】,【怎么用】,【底层实现原理】,【核心代码解析】这几个点来阐述。
二、微服务简介
1.什么是微服务
微服务最早的概念源于 Martin Fowler 于 2014 年 3 月 25 日写的一篇文章 Microservices(中文版翻译点击查看)(具体细节读者有兴趣可以自己去看)。其实说的通俗一点就是只要能对外提供接口服务就是微服务。例如,你用spring boot写了一个controller,访问返回一个hello字符串,其实这就是一个微服务(源码),如下图所示:
2.为什么要用微服务架构
笔者刚刚2011年参加工作那会,基本上绝大多数的系统都是所有功能集成在一起的。那这样的架构有什么优缺点呢?相比下微服务又有什么优劣好坏呢
集中型服务架构优点:
a.编码调试简单,因为所有的代码全集中在一个项目之中,团队协作时可以直接debug调试程序,出了问题能很快定位到问题所在。
b.系统复杂度可控,数据存储时也不会出现分布式事务,不用考虑数据一致性的问题。
c.并发和负载不高的时候,性能较好(毕竟是服务内部调用,少了网络传输序列化和反序列化这个环节)。
集中型服务的缺点:
a.可用性差,一旦遇到宕机就无法再对外提供服务;
b.可伸缩性较差,水平扩容和迁移困难,例如电商平台搞类似双十一促销活动时,流量可能是平时的好几倍甚至是好几十倍,遇到这种临时扩容难度高,虽然能够通过lvs+nginx解决横向扩容的问题,但是大型系统一般对系统配置要求较高,都是采用的实体机,搭建环境,调试以及后续的迁移都需要付出较大的代价,另外数据库也是重要的性能瓶颈;
c.代码高度耦合度,维护成本高,团队协作时,如果小伙伴代码有问题,很可能导致整个系统跑不起来;
d.性能瓶颈难以突破,虽然通过强行堆机器配置能缓解部分压力,但是毕竟单机网络,磁盘IO,内存等资源也是有限的,尤其是堆的越高服务器成本也会成对数增长。笔者曾经遇到过某个服务器(128G内存+42核+10T SSD)的磁盘IO长期保持98%,一遇到并发就崩。
也正是由于上述的这些问题,后面技术专家们就开始琢磨如何将一个大型的系统拆解成多个独立的小系统。中间就出webservice这类技术,其实本质上这也是微服务,只不过性能和灵活性较差而已,例如webservice一旦服务提供者的ip和端口改了会影响上游调用者,需修改配置重启后方能恢复正常。针对这类问题,引入服务治理的概念,我们除了需要做到提供远程调用之外,还需要提供服务注册,负载均衡,服务降级,限流,日志埋点,网关路由,监控等功能保证服务高性能,高可用,容灾等特性
3.微服务的技术栈有哪些
在介绍各个组件之前,笔者先阐述一下微服务,Spring cloud,Dubbo,RPC之间的关系,现在网上的说法也是五花八门,笔者起初在学习微服务系列技术之前也是很疑惑,面试的过程之中也是常见的考题。
- 微服务只是一个概念和申明,正如笔者开头所说,只要能对其他系统提供接口的服务都能称之为微服务,现在网上的说法基本上已经把Spring Cloud和微服务划了等号,这其实是不对的,只不过是Spring Cloud解决的比较全面而已,具体的如下图所示:
- Spring Cloud是一整套微服务的技术解决方案,目前也有两套方案,一套是Spring Cloud Netflix,另一套是Spring Cloud Alibaba,含服务注册发现组件(Euraka,Nacos),负载均衡组件(Robbin,loadbalance),配置中心组件(Config+Git,Nacos,Apollo),熔断(Hystrix,Sentinel),链路监控(Pinpoint,Skywaying)等。这里笔者温馨提示,目前Netflix已经不再维护了,所以建议大家也可以多了解一下Spring Cloud Alibaba,两套的技术可以混着用。另外本质上Spring Cloud是一个maven项目,集成了各个组件(Spring Cloud Netflix源码,Spring Cloud Alibaba源码),如下图所示:
- RPC是一种规范而已,其实就类似咱们Java里面的interface,定义了某个方法已经传什么参数,返回什么参数,具体的实现则由相关的框架去实现。主要含三大块,通信协议,序列化技术,以及框架,前面介绍微服务的图里面已有说明。
- Dubbo是一种非常流行的RPC的框架。
三、主流微服务解决方案
服务注册中心对比
Feature | Consul | Zookeeper | Nacos | Euerka |
服务健康检查 | 服务状态,内存,硬盘等 | (弱)长连接,keepalive | 连接心跳 | 可配支持 |
多数据中心 | 支持 | — | — | — |
kv存储服务 | 支持 | 支持 | 支持 | — |
一致性 | raft | paxos | raft | — |
cap | ca | cp | cp/ap | ap |
使用接口(多语言能力) | 支持http和dns | 客户端 | http/grpc | http(sidecar) |
watch支持 | 全量/支持long polling | 支持 | 支持 long polling | 支持 long polling/大部分增量 |
自身监控 | metrics | — | metrics | metrics |
安全 | acl /https | acl | https支持(弱) | — |
spring cloud集成 | 已支持 | 已支持 | 已支持 | 已支持 |
说明:从笔者自己的使用情况看4个其实差别不是特别大,但是界面的友好度来说,Consul和Nacos会好很多,另外Nacos相对来说会灵活一些,同时支持CP和AP两种模式。但是从社区的活跃度和稳定性来说,肯定是Consul要强的多,另外Consul是Go语言研发的,所以性能天然就有优势,所以综合来看目前Consul是最佳选择。ZK和Eureka本身都有自身的短板,尤其是Eureka已经停止维护了。
配置中心对比
Feature | Spring Cloud Config | Apollo | Nacos |
开源时间 | 2014.9 | 2016.5 | 2018.6 |
配置实时推送 | 支持(Spring Cloud Bus) | 支持(HTTP长轮询1S内) | 支持(HTTP长轮询1S内) |
版本管理 | 支持(Git) | 支持 | 支持 |
灰度发布 | 支持 | 支持 | 待支持 |
权限管理 | 支持 | 支持 | 待支持 |
多集群 | 支持 | 支持 | 支持 |
多环境 | 支持 | 支持 | 支持 |
多环境 | 支持 | 支持 | 支持 |
多语音 | 只支持Java | Go,C++,Python,PHP,Java,.Net,OpenAPI | Go,C++,Python,PHP,Java,.Net,OpenAPI |
单机部署 | Config-Server+Git+Spring Cloud Bus(支持配置实时推送) | Apollo-quickstart-MySQL | Nacos单节点 |
分布式部署 | Config-Server(2)+Git+MQ(部署复杂) | Config(2)+Admin(2)+Portal(2)+MySQL(部署复杂) | Nacos(3)+MySQL(部署简单) |
配置格式校验 | 不支持 | 支持 | 支持 |
通信协议 | HTTP和AMQP | HTTP | HTTP |
数据一致性 | Git保证数据一致性,Config-Server从Git读取数据 | 数据库模拟消息队列,Apollo定时读消息 | HTTP异步通知 |
单机读 | 7(限流所致) | 9000 | 15000 |
单机写 | 5(限流所致) | 1100 | 1800 |
3节点读 | 21(限流所致) | 27000 | 45000 |
3节点写 | 5(限流所致) | 3300 | 5600 |
说明:从笔者的使用情况看,Apollo会成熟稳定不少,但是确实是过于重了,对于初学者来说可能Nacos更容易上手,另外关于灰度发布这一块,笔者认为这应该是网关的职责范畴,倒是权限这一块Nacos确实是做的比较差(后续会维护)。Config没什么好说的,使用上不太友好,也和Git是强耦合。
网关对比
组件 | RPS(request per second) |
Spring Cloud Gateway | Requests/sec: 32213.38 |
Zuul | Requests/sec: 20800.13 |
Linkerd | Requests/sec: 28050.76 |
详细信息请参考:
熔断器对比
| Sentinel | Hystrix |
隔离策略 | 基于并发数 | 线程池隔离/信号量隔离 |
熔断降级策略 | 基于响应时间或失败比率 | 基于失败比率 |
实时指标实现 | 滑动窗口 | 滑动窗口(基于 RxJava) |
规则配置 | 支持多种数据源 | 支持多种数据源 |
扩展性 | 多个扩展点 | 插件的形式 |
基于注解的支持 | 即将发布 | 支持 |
调用链路信息 | 支持同步调用 | 不支持 |
限流 | 基于 QPS / 并发数,支持基于调用关系的限流 | 不支持 |
流量整形 | 支持慢启动、匀速器模式 | 不支持 |
系统负载保护 | 支持 | 不支持 |
实时监控 API | 各式各样 | 较为简单 |
控制台 | 开箱即用,可配置规则、查看秒级监控、机器发现等 | 不完善 |
常见框架的适配 | Servlet、Spring Cloud、Dubbo、gRPC 等 | Servlet、Spring Cloud Netflix |
说明:Hystrix相对Sentinel来说还是做的比较简单,由于目前Sentinel对Webflux支持的不是太好,笔者也是一直没有采用Sentinel,但客观的讲Sentinel还是比较强大,界面也相当的友好。