1 微服务历史
- 2005年:Dr. Peter Rodgers提出"Micro-Web-Services"概念
- 2011年:一个软件架构工作组使用"microservice"来描述一中架构模式
- 2012年;这个工作组正式使用"microservice"来代表这个架构
- 2012年:ThoughtWorks的James Lewis针对微服务概念发布演讲
- 2014年:James Lewis和Martin Flower合写了一篇学术性文章,详细阐述微服务
虽然微服务也提到了服务,SOA中也有服务这个概念,但是并不是说两个是同一个东西
2 微服务和SOA关系
微服务和SOA的关系和区别有几个典型的观点
- 微服务是SOA的实现方式:SOA是一种架构理念,而微服务是SOA的一种具体实现方式,使用了Http RESTful来实现ESB
- 微服务是去掉ESB后的SOA:可以发现微服务中没有ESB这种具体的总线概念,都是直接使用http请求来访问其他服务
- 微服务是一种SOA相似但本质上不同的架构概念:两个虽然类似,但本质上只是都拥有了服务这个概念的两种架构
微服务与SOA实际对比后可能才能了解到这两个架构的关系
- 服务粒度:SOA要更粗一些,而微服务则要细一点
- 服务通信:SOA同意ESB作为通信组件负责服务定义,服务路由,消息转换,消息传递,总体是重量级的实现,而微服务则是推荐同意协议和格式,方便传输和转换
- 服务交付:SOA并没有交付要求,更多是考虑兼容现有的系统,微服务则是要求快速交付,一般要采取自动化测试、持续集成、自动化部署等敏捷开发的最佳实践,不然一旦服务不断增加,就会导致交付成本增加,可以想象100多个服务要进行重新上线会有多么恐怖
- 应用场景:SOA更适合庞大、复杂、异构的企业级系统,因为重构和优化成本过高,只能使用兼容模式进行处理,微服务责适用于快速、轻量级的互联网系统,因为变化快,需要快速尝试,并且新兴面对的不是老旧系统
- 对比表格如下,可以得出SOA和微服务本质上就是两种不同的架构只不过都有服务这个概念
对比维度 | SOA | 微服务 |
---|---|---|
服务粒度 | 粗 | 细 |
服务通信 | 重量级,ESB | 轻量级,例如HTTP RESTful |
服务交付 | 慢 | 快 |
应用场景 | 企业级(老旧系统) | 互联网 |
可以发现微服务是一种优秀的架构模式,且比SOA要优秀,那我们应该把架构重构为服务吗?
答案是不一定,请记住三原则中的合适原则,微服务的需求你用的上嘛?且在SOA适用的系统中,转换为微服务只会徒增实施难度和成本
3 微服务的陷阱
微服务不是无所不能且全是优点,能不能用微服务重点是合适原则,如果不考虑团队规模,业务发展,基础技术支持,直接上微服务,那么只会在这个坑里越陷越深
坑
- 服务划分过细,服务间关系复杂:单个服务复杂度确实下降了,但是你几百个,几十个微服务,也不见得系统的整体复杂度下降了,只不过是把单服务内部复杂度转移到了系统整体上(笑容不会消失,只是转换到了我的脸上😊)
- 服务数量多,团队效率下降:团队规模要是小一点,一个负责好几个服务是真恶心,开发、单元测试、打包、部署、整体测试等多个环节都会恶心到你🤮
- 调用链长,性能下降:如果不拆分那么就是在机器内部进行逻辑运算和方法调用,快的一批,但是微服则会一个服务调另一个服务,要是中间遇到网络分区等问题,可能导致接口拥堵等问题
- 调用链长,问题定位难:本身我们看日志或者异常的message就能找到问题,但微服务存在故障扩散现象,快速定位就变得异常难
- 没有自动化支持,无法快速交付:如果没有系统化系统支持,那么全是人工去测试,去部署,去交付,去实施,那么出问题是必然的(如果你没有,那么你总会遇到的),而且速度还是硬伤。
- 没有服务治理,微服务数量多了后管理混乱:本质上就对熔断,限流,降级,服务注册和发现,以及负载均衡,远程调用的方案设计要更加的合理符合直觉
4 微服务最佳实践
微服务的坑可以提炼为:拆的过细,基础设施不健全,微服务不轻量级
带着以上问题,看看微服务的最佳实践该怎么做
4.1 服务粒度
粒度划分过细可能会导致出现问题,但是过粗又会增加每个服务的负载导致系统的性受到影响,所以要划分的合适这是解决问题的关键,作者给出的建议是基于团队规模进行拆分
三个火枪手:即一个微服务三个人负责开发,并且会随着人数的增加而继续拆分微服务,如:目前团队有6个人,那就拆成两个微服务,如果增加到了12个人,同时系统的功能和复杂度也会增加,这时候,就可以将2个微服再分别拆为两个,相应降低了单个微服务的复杂度
?为啥是三个人负责一个呢:为啥不是2个人,不是4个人
- 简单->三人成虎😊,从科学角度出发,如果3个人负责一个系统,系统的复杂度刚好达到每个人都能全面理解整个系统,还能分工。
- 还能形成高可用,即使一个人请假了,还有两个人,加班不会觉得孤独😄
- 且三个人能形成有效的讨论,能快速达到一致意见,如果是两个可能发生分歧👀,一个人的话可能陷入思维盲区,更多人的话可能出现有人摸鱼
4.2 拆分方法
定好了拆分大小后,就需要确认拆分的方式了,一般有如下几种:基于业务逻辑拆分、基于可扩展拆分、基于可靠性拆分、基于性能拆分
- 基于业务逻辑拆分:这是一种常见的拆分方式,简单来说就是按照功能模块划分
- 首先要计算大概服务数量范围,再确认合适的职责范围:如果团队规模是10个人,划分4个服务,那么登录,注册,用户信息管理,可以划分到用户服务的范围作为微服务,如果是100人,那么用户登录就可以是一个单独的微服务了
- 基于可扩展拆分:将稳定的服务和经常迭代的服务拆分开,稳定的可以粒度划分更粗,毕竟不会再进行升级和迭代所以系统内部的复杂度高一点也没问题,而需要快速迭代的服务则划分细一点,方便开发对具体功能敏捷开发
- 基于可靠性拆分:本质上来说就是将核心业务和非核心业务拆分,能够对核心的业务进行高可用的机器冗余方案,非核心业务没必要也不需要进行高可用冗余,反而会导致成本上升
- 基于性能拆分:和上面的可靠性拆分类似,都是为了进行机器冗余时对关键的需要进行高性能运算的服务拆分出来进行机器扩展,降低机器冗余的成本
上述的拆分方式并不是只能选择一个,可以在系统划分时组合排列,比如使用了性能划分后,还可以进行可靠性划分
4.3 基础设施
微服务的关键确实是“微”、“轻量化”,但是其“自动化”也是一个重要点,如果因为"自动化"不到位,即使服务划分的再好,再细节,每次部署、测试的时候以及上线等问题带来的资源、时间消耗就不止服务划分、轻量化开发时消耗的时间了
基础设施如下
- 服务发现
- 服务路由
- 服务容错
- 服务监控
- 服务跟踪
- 服务安全
- 自动化测试
- 自动化部署
- 配置中心
- 接口框架
- API网关
可以发现,基础设施的搭建即多又繁琐,像是把SOA的ESB转移到了基础设施上,但是每个基础设施又有其作用
- 自动化测试:原本大一统的系统拆分为多个独立运行的“微服务”,且服务之间的接口数量大大增加,并且微服务还提倡快速交付,开发周期短,如果测试等工作不能自动化,要么增加人工成本,要么增加研发成本(配置好自动化测试)
- 自动化测试包含:单元测试、单系统集成测试、系统间接口测试,至少都要做到接口测试自动化
- 自动化部署:微服务多,手动部署会有风险和问题,自动化能相对解决这个问题
- 包括:版本管理、资源管理、部署操作、回退操作等
- 配置中心:微服务的配置,生产环境和开发环境以及测试环节都是不一样的,且不同的微服务可能有相同的配置,如果改了其中一个,还要手动改其他的。所以配置中心就是统一配置,多个微服务都可以使用同一个配置信息,改了配置文件后,所有微服务都会生效。
- 包括:配置版本管理,增删改查配置、节点管理、配置同步、配置推送等
- 接口框架:我们需要统一整个微服务的通信协议以及序列化协议,能够方便我们接收请求以及处理响应,以及处理数据格式
- API网关:微服务之间是互联互通的,内部你怎么去请求怎么去交流有内部的方式,如果外部系统或者请求,就不知道该如何访问某个服务的接口,且接口权限也不好统一
- 网关能很好解决这个问题,作为微服务统一的入口,可以进行鉴权、权限控制、传输加密、请求路由转发、流量监控,请求日志等
- 服务发现(当前服务怎么找到依赖的服务的地址):微服务数量多,如果各个服务之间的依赖使用手工录入的话,工作量大,并且配置中心很多时候可能也会依靠服务发现,去做自动化配置,且一个服务扩容后该怎么路由达到负载均衡等,以及灰度发布
- 自理式:指每个微服务完成自己的服务发现
- 代理式:服务消费者不直接与服务提供者通信,而是通过一个代理(通常是负载均衡器或代理服务器)来间接访问服务
- 服务路由:有了服务发现之后,对于某次具体的调用,需要从符合条件的节点中选择一个发起请求
- 服务路由和服务发现紧密相关,自理式服务发现的服务路由是微服务内部实现的,对于代理式服务路由是有LB(负载均衡)系统实现的
- 常见算法有:随机路由、轮询路由、最小压力路由、最小连接数路由等
- 服务容错:拆分微服务后,单个微服务的故障率变小了,但是被其他服务影响导致故障的概率却变大了,单个微服务故障影响返回减少,但是导致上下游发生故障后,影响面积却又扩大了,所以控制故障扩散就是服务容错的能力
- 常见的服务容错:请求重试、流控、服务隔离
- 请求重试:重新向同一个微服务节点重新发送请求
- 流控:也就是我们常说的限流,通常应对某类微服务请求突增,且由于系统容量限制,无法快速应对突发容量,通常微服务节点的流控由自己实现
- 服务隔离:当某个微服务故障时,让其下线避免故障扩散,隔离又分为:主动隔离、被动隔离、手动隔离
- 主动隔离指微服务自己发现自己异常后,主动注销自己->降级
- 被动隔离指被系统发现异常频率等触发了设置的阈值,被系统注销->熔断
- 手动隔离指人工判断系统故障后,手工操作注销
- 三者可以一起使用,能够更好的保证服务故障不扩散
- 服务监控:实时收集微服务信息,包括但不限于机器、网络、进程、接口调用数等
- 服务监控作用有很多:收集信息,预警
- 收集信息实时分析可以避免故障后再分析,减少处理时间
- 可以在实时分析的基础上进行预警,提前发现问题萌芽,扼杀!
- 服务跟踪:跟踪每次请求的在微服务中的完整路径,监控是很难实现的,且每个请求都这样的话,数据量会非常大
- 监控和跟踪的关系就是宏观和微观关系,监控统计了路径的结果,跟踪则是每次路径,现在的服务跟踪大部分都是基于Google的Dapper论文《Dapper,a Large-Scale Distributed Systems Tracing Infrastructure》,技术关键点如下
- 标注点: 标注点会在一个完整的调用链中有自己的id,类似于seata的分布式事务id,而且我们可以控制在哪里打上标注点
- 比如一个元数据落标,我们可以在任务开始时标记一下,在数据库记录当前任务的id,整个任务过程都是用这个id去标记和入库,当任务结束后,我们就可以查看每次任务的流程以及各个标注点的信息
- 跟踪树和span:标注点可以说是很多跟踪任务的通用解决方案,但是在微服务的服务跟踪中,不仅需要记录标注点,还需要集合调用链以及分支结构,比如A服务调用了C和B,C又调用了D,B又调用了E,此时就出现了分支如下:所以span就是每个节点,而跟踪树就是由每个节点的span组成的树结构,每个span中又可以有标注点
- A
- B
- E
- C
- D
- 标注点: 标注点会在一个完整的调用链中有自己的id,类似于seata的分布式事务id,而且我们可以控制在哪里打上标注点
- 服务跟踪主要有两个目的:采样跟踪、染色跟踪
- 采用跟踪:根据一定概率对请求进行采样跟踪,基于采样数据进行分析,通常用于检查性能不足等,对系统消耗小且压力小
- 染色跟踪:针对某个特殊请求进行跟踪,比如某个特定用户id,某个特定的业务对象id,常常因为这些特定对象会导致系统出现问题,同时还不是大面积的问题,所以很难定位问题,需要进行染色跟踪的用户id或业务对象id
- 监控和跟踪的关系就是宏观和微观关系,监控统计了路径的结果,跟踪则是每次路径,现在的服务跟踪大部分都是基于Google的Dapper论文《Dapper,a Large-Scale Distributed Systems Tracing Infrastructure》,技术关键点如下
- 服务安全:简单来说就是每个微服务的资源也需要进行鉴权和保护,比如拥有A权限的微服务可以去访问用户信息微服务的修改接口,拥有B权限的微服务能够访问用户信息的的获取接口
- 服务安全分为三个部分:接入安全、数据安全、传输安全
- 接入安全:只有经过允许,某个微服务才能访问另一个微服务,否则会被拒绝
- 数据安全:各个接口需要对应权限和授权后才能访问
- 传输安全:指某些敏感数据需要在传输过程中,防窃取、防篡改保证数据的真实有效
- 通常可以集成到配置中心系统进行实现,单独配置某个微服的接入安全策略和数据安全策略信息
- 服务安全分为三个部分:接入安全、数据安全、传输安全
5 总结
- 微服务概念的历史要早得多,也不是Martin Flower创造出来的,Martin只是将微服务进行了系统的阐述。
- 微服务是一种和SOA相似但本质上不同的架构理念。
- 微服务的三个关键词:small、lightweight、automated。
- 微服务和SOA不存在孰优孰劣,只是应用场景不同。
- 微服务并不是没有代价,而是会带来系统复杂度、运维复杂度、性能下降等问题。
- 微服务拆分的粒度遵循“三个火枪手”原则。
- 真正决定微服务成败的,恰恰是那个被大部分人都忽略的"自动化"(automated),而不是“小”(small)和“轻量级”(lightweight)。
- 微服务并不是很多人认为的那样又简单又轻量级,要做好微服务,基础设施是必不可少的。