“读书足以怡情,足以长才。读史使人明智,读诗使人灵秀,数学使人周密,科学使人深刻,伦理学使人庄重,过度学习使人疯魔;凡有所学,皆成性格。”
--弗朗西斯·培根《论学习》
是的没错,格格不入那句是我编的,看看下图就明白了。
文 | 刘启伟
正文
最近本人刚经历了工作调动,正处于持续学习的状态。在这过程中微服务这个关键词多次出现,而刚好我以前写的应用都是单体架构,未有过微服务架构开发经验,因此就微服务我展开了进一步学习。本文算是一篇学习笔记吧,旨在分享学习带给我的快(zhe)乐(mo),希望能和大家一起进步。
为什么要用微服务架构
传统应用一般是一站式开发,在发展初期功能较少,单体应用可以较好地支撑。但随着功能越来越多,系统越来越复杂,单体应用会逐渐暴露出代码维护难、部署不灵活、稳定性和扩展性差等问题。
图注:当我试图为单体应用添加新功能时
为了解决单体应用存在的问题,微服务应运而生。微服务是指将单体应用拆分成多个微服务,每个微服务实现单一的业务功能,运行于独立的进程之中,实现高内聚低耦合。当然微服务也有一些缺点,例如运维更复杂等,具体可翻阅段老师撰写的微服务六脉神剑系列(微服务之六脉神剑 | (壹)揭开微服务的神秘面纱),里面详细介绍了微服务架构、适用项目及微服务改造等内容。
目前常见的微服务架构解决方案有Spring Cloud 和 Dubbo 等,由于之前接触过Spring 全家桶的冰山一角,所以本文选用 Spring Cloud 进行微服务实战。
Spring Cloud 常用组件介绍
Spring Cloud 拥有诸多子项目,功能组件组成相当复杂,这里只介绍最常用的几个组件。
1 Eureka
Eureka是Spring Cloud中的服务治理组件,分为Eureka server和Eureka client。Eureka client集成在各个微服务项目中,项目在启动或者信息发生变化时会将网络地址等信息注册到Eureka server上。Eureka server通过定期心跳报文与Eureka client通信,进行服务续约与注销等操作,维护服务注册表。服务消费者可以从服务注册表中查询服务提供者的网络地址,再用该地址调用提供者,从而避免在代码中使用硬编码导致无法适应微服务动态伸缩等问题。
Eureka server的高可用很重要,通常是通过部署多个Eureka server节点,并在Eureka server中集成Eureka client,多个节点互相注册,同步注册表,组成集群。同时,在各个Eureka client中也会缓存注册表,避免出现Eureka server集群挂掉后所有微服务故障的情况。
2 Ribbon
Ribbon组件在服务消费者端实现了软件负载均衡算法,默认有轮询、随机、负载优先等多种均衡算法。配合Eureka一起使用,当服务提供者向Eureka server注册了多个实例时,服务消费者获取提供者信息后,再由Ribbon根据负载均衡策略选择一个提供者访问。
3 Feign
Feign组件实现了声明式、模板化的HTTP客户端。微服务之间一般是通过基于HTTP的Restful API通信,如果每个请求都要写HTTP客户端代码,会存在大量重复工作,而用Feign可以大大简化,通过接口和注解就能实现HTTP客户端调用。
Feign还有一个很明显的好处,就是默认集成了Ribbon负载均衡器和Hystrix容错,只需通过配置就能使用。
4 Hystrix
微服务是分布式架构,涉及很多服务间的调用,当某个服务不可用时,如果没有容错机制,调用这个服务的其他服务会出现大量线程阻塞,最终因资源耗竭导致不可用,而这些服务不可用同样可能会引起更多的服务不可用,形成“雪崩效应”。
Hystrix组件正是为服务间调用提供了容错机制,主要通过以下几点实现:
① 资源隔离:
Hystrix为每个依赖维护了一个独立的线程池或信号量,当资源全部占用后,新的请求被拒绝,而不是排队,这样就保证了依赖不会占用过多的资源。
② 断路器:
当某个依赖在时间窗口中调用失败次数过高,就会打开断路器,新的请求会直接失败,而不是等待。
③ 回退机制:
请求失败、超时或断路器打开时,会执行回退逻辑,实现一些友好提示等。
5 Zuul
Zuul组件是微服务的网关,默认集成了Ribbon和Hystrix。Zuul网关位于客户端与各个微服务之间,所有请求会先经过Zuul,功能上相当于一系列过滤器的组合,可实现统一认证、监控与审查、动态路由、负载分配、静态响应处理等功能。
Zuul网关通常具有很高的负载,且可用性要求很高,所以其通常是一个集群。用户的请求先经过Nginx等一层负载均衡再进入到Zuul网关集群,然后再到内部的微服务。
6 Spring Cloud Config 与 Spring Cloud Bus
微服务在运行时配置往往是实时变化的,为了避免每次配置更改都要重新打包部署,Spring Cloud使用Config组件统一管理配置。Config组件分Config server和Config client,server默认使用git作为后端管理各个项目的配置文件,client集成在各个项目中,向server请求配置。当配置更新时,手动请求client的/refresh端点就会触发重新加载配置。
但实际上基本不可能用手动方式来刷新配置,所以Config常与Bus消息总线配合,当配置更新时,Config server通过消息总线分享状态,Config client再进行配置刷新,从而实现动态配置更新。
Spring Cloud 微服务实践
自己动手,丰衣足食。上面第二部分介绍了各个组件,这一部分将进行实战,使用Spring Cloud组件搭建起简单的微服务架构,再验证下各个组件的功能。
1 实验架构说明
最近口罩预约话题很火,所以我也来蹭蹭热度,假设服务提供者是管理用户信息的微服务(user-microservice),服务消费者是口罩预约信息登记的微服务(mask-appointment-microservice),口罩预约微服务需要调用用户微服务查询用户是否有资格参与口罩预约。因条件有限(偷懒),未使用统一动态配置及Zuul网关集群,实验架构如下图所示:
2 架构搭建
Spring Cloud很多组件已经发展得比较成熟了,基本使用注解+配置的方式就能实现。为了方便,本文使用IDEA的Spring Initializr快速搭建项目。
① Eureka Server
Spring Initializr搭建好项目后,加入maven依赖,做好相关配置,然后在启动类中添加@EnableEurekaServer注解就完成了。由于本文搭建了2个Eureka Server组成集群,因此在配置中分成两部分,设置2个实例的启动端口及向对方互相注册,同步注册表。
② Zuul
同Eureka server差不多,通过配置和注解实现即可。
③ user-microservice
管理用户信息的微服务,为了方便,使用h2作为测试数据库,DAO接口直接使用Spring boot JPA中的JpaRepository接口。本微服务向外提供了一个API根据用户ID查询用户信息,定义在UserController中。项目结构及配置文件如下图所示。
④ mask-appointment-microservice
口罩预约的微服务(只是假设,并没有实现业务的),暴露/user/id节点,向user-microservice的/id节点查询用户信息,例如在实际应用中查询用户是否登记到健康情况,是否有资格预约口罩等。API调用是通过Feign client实现,Feign中还集成了Ribbon负载均衡及Hystrix容错。项目架构和配置文件如下图所示。
⑤ Zipkin-server
同Eureka server差不多,通过配置和注解实现即可。该服务只要是测试微服务跟踪功能,收集每个微服务的跟踪数据并可视化
3 测试验证
使用jar包依次启动各个微服务,各服务部署端口如下:
微服务名称 | 部署端口 |
Eureka-server(2个实例) | 8071/8072 |
user-microservice(2个实例) | 8080/8081 |
mask-appointment-microservice | 8085 |
zuul-proxy | 8075 |
zipkin-server | 8090 |
① Eureka服务注册测试
在浏览器中分别访问http://localhost:8071/和http://localhost:8072/ ,观察到服务注册成功,且显示的服务实例数和实际一致。
② 微服务API调用测试
访问mask-appointment-microservice的/user/id,调用user-microservice 的/id 查询用户信息,查询成功。
③ Ribbon负载均衡测试
多次访问mask-appointment-microservice的/user/id,查看两个user-microservice实例的控制台日志,发现两个实例轮流被访问,因为Feign中的Ribbon默认策略是轮询。
④ Hystrix容错测试
关闭2个user-microservice实例,再次访问mask-appointment-microservice的/user/id,此时访问失败,返回Hystrix回调函数中定义的默认用户信息。
但查看mask-appointment-microservic的/actuator/health监控节点发现断路器状态仍为“UP”,没有启动。
这是因为当前只失败了1次,断路器需要在时间窗口中失败次数超过门限才会启动。用单身多年的手速刷新浏览器一段时间,此时发现断路器状态为“CIRCUIT_OPEN”,即启动了。
⑤ Zuul网关代理测试
通过Zuul网关代理访问mask-appointment-microservice的/user/id,访问成功。同时通过Zuul的管理端点可以看到网关的路由映射和过滤器信息。
⑥ 微服务监控测试
通过Hystrix开放的监控节点/actuaror/hystrix.stream可以获取当前微服务调用其他服务次数、成功数等运行指标,如下图所示,实际中还可结合Turbine聚合监控数据,再用Hystrix Dasboard可视化,用于分析服务状态。
通过整合Sleuth组件可以收集微服务的跟踪数据,并发送给Zipkin等工具可视化。跟踪数据体现出各微服务的业务逻辑耗费时间和网络延迟等,对网络问题的定位很有帮助。
当监控数据比较多或者监控服务处于不同网络平面时,可以用消息中间件统一收集监控数据,再分发给turbine和zipkin等,实现微服务状态监控和分布式跟踪等功能。
本文是我第一篇(可能也是最后一篇)微服务Spring Cloud学习笔记,举的栗子都很简单,如果要深入学习的话还是得多看相关的书籍。
最后,祝正式复工的大家身体永远0 error,0 warning。
本期嘉宾
本期嘉宾 | 刘启伟 广东移动网管中心“新人”,目前在网络云团队计算与虚拟化专业中学习。熟悉Python、Java及前端开发。中国移动2019年网络运维IT自主研发大赛一等奖获得者。(由于本人太帅,照骗不敢露脸)
你可能还喜欢
一手经验 | 5G-NFV搭建网络云CMDB
微服务之六脉神剑 | (壹)揭开微服务的神秘面纱
微服务之六脉神剑 | (贰)为什么谈论微服务时,总是会谈起DevOps?
微服务之六脉神剑 | (叁) 如何进行服务拆分和演进?
微服务之六脉神剑 | (肆) 一个480微服务的治理框架选择
微服务之六脉神剑 | (伍) 不得不说的五个关系
微服务之六脉神剑 | (陆) 蓦然回首,大师在召唤