面试复习之SpringCloud篇
一、微服务框架
1.SpringCloud框架
一个基于SpringBoot开发的、用来实施微服务架构的综合性解决方案。基于组件化的设计思想,主要涉及Eureka、Ribbon、Hystrix、Feign、Zuul、Config、Bus、Stream、Sleuth组件。
2.微服务架构设计
单体应用按照一定原则(比如DDD)拆分为若干个可独立部署的小服务,不同服务之间采用Http的Restful API风格通信,而传统的系统架构设计是基于对象或者业务类型搭建的一个单体项目。
3.微服务带来的好处
去中心化治理和去中心化管理数据,每个微服务的技术栈可以灵活选择,不必约束大家都完全一致,比如数据存储,在MySQL和MongoDB等之间可以选择1个或者多个方案,自主选择是否需要分库分表。
4.微服务带来的挑战
对基础运维设施的自动化程度要求更高(CICD)
系统设计变得更加复杂(网络延迟、分布式事务、异步)
对外服务接口管理的规范化(严格遵守开闭原则)
5.实施微服务架构,团队建议按照业务/产品线拆分
一个内聚的小团队沟通成本低
团队间边界清晰
6.为什么选择SpringCloud框架?
因为它是针对分布式系统拥有众多开源子项目的一个大型综合项目,开源社区可持续发展,生态良好,开发者众多。
二、配置方式(主要介绍2种)
1.YAML格式,采用阶梯化缩进的格式。
spring:
profiles: dev
application:
name: zuul-gateway
server:
port:8080
eureka:
client:
serviceUrl:
defaultZone: http://eureka-server:9527/eureka/
PS:
YAML将属性加载到内存中存储时是有顺序的,所以不要依赖YAML文件的内容顺序。
YAML无法通过@PropertySource注解来加载。
2.properties文件
dev =
zuul-gateway =
8080 =
http://eureka-server:9527/eureka/ =
三、Eureka
1.基于Netflix Eureka二次开发的服务治理组件。
Eureka组件分为客户端和服务端,提供了完备的Restful API,因此支持非Java语言体系构建的微服务应用。CAP定律满足AP,只保证可用性和可靠性。
2.什么是服务治理?
核心是服务的自动化注册和发现。
3.注册中心
4服务注册
Provider端启动时,会自动向注册中心注册需要对外发布的服务接口。
5.服务发现
Consumer端启动时,会自动向注册中心订阅需要的远程服务接口列表,这个列表会在本地缓存,会周期性的查询远程服务接口列表并刷新本地缓存。
6.服务调用
Consumer端在调用远程接口时,依照负载均衡策略先从本地缓存的远程服务接口列表中查找一个服务实例,再来调用这个服务实例提供的服务接口,实际是进行一次Http请求服务。
7.应用程序启用Eureka注解
@EnableDiscoveryClient
@SpringBootApplication
public class Application{
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
四、Ribbon
1.基于Netflix Ribbon二次开发的基于Http和TCP的客户端负载均衡组件。
工具类框架,不能独立部署。通过二次开发封装,将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
2.负载均衡
对系统的高可用、网络压力的缓解、服务器线性扩容的一种重要手段。
3.如何使用?
消费者通过被@LoadBalanced注解修饰的RestTemplate类来实现远程服务接口的调用即可,RestTemplate类是一个Http模版化调用工具,会使用Ribbon的自动化配置,默认的负载均衡策略是线性轮询。
4.Ribbon核心类
IClientConfig客户端配置(Ribbon)
ILoadBalancer负载均衡器
IRule负载均衡策略(随机、轮询、重试、权重计算)
IPing实例检查策略
ServerList<Server>实例清单
ServerListFilter<Server>实例清单过滤器
LoadBalancerInterceptor拦截器
5.参数配置
Ribbon全局配置,形如ribbon.<key>=<value>
#开启Eureka主动对Ribbon服务列表的维护
ribbon.eureka.enabled = true
#创建连接的超时时间
ribbon.ConnectTimeout = 300
#请求处理的超时时间
ribbon.ReadTimeout = 700
#对所有Http请求方式的请求处理都进行超时重试
ribbon.OkToRetryOnAllOperations = true
#对当前实例的重试次数
ribbon.MaxAutoRetries = 1
#切换实例的重试次数
ribbon.MaxAutoRetriesNextServer = 2
#开启自动重试,默认是关闭状态
spring.cloud.loadbalancer.retry.enabled = true
#断路器超时时间必须大于Ribbon的超时时间,否则重试不会生效
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 3000
Ribbon指定客户端配置(会覆盖全局配置),形如<client>.ribbon.<key>=<value>
#服务提供者QRCodePay-service的客户端创建连接的超时时间
QRCodePay-service.ribbon.ConnectTimeout = 1000
查看Ribbon可配置参数
com.netflix.client.config.CommonClientConfigKey
五、Feign
1.基于Netflix Feign二次开发的客户端声明式服务调用组件。
整合了Ribbon和Hystrix,提供了声明式Web服务客户端定义方式。对RestTemplate进一步封装,只需创建一个接口和启用注解配置,即可完成对服务提供者的接口绑定。
2.应用程序启用Feign注解
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class Application{
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
3.接口启用Feign注解
#注解参数不需要区分大小写
@FeignClient("QRCodePay-service")
public interface HeartController{
@RequestMapping("/query")
String heart(@RequestParam("uuid"), String uuid);
}
PS:Feign接口必须指定方法的参数名称绑定。
4.Http通信工具包
Feign支持多种HttpClient工具包,如OkHttp及Apache HttpClient。
针对Apache HttpClient的典型配置:
#Feign启用HttpClient
feign.httpclient.enabled = true
5.序列化
JSON与对象之间转换。
6.请求压缩
feign.compression.request.enabled = true
feign.compression.response.enabled = true
#压缩的请求数据类型
feign.compression.request.mime-types = text/xml,application/xml,application/json
#超过这个值才会进行压缩
feign.compression.request.min-request-size = 2048
7.日志配置
#<FeignClient>为接口的完整路径
logging.level.<FeignClient> = DEBUG
logging.level.org.springframework.web.servlet.DispatcherServlet = DEBUG
8.服务分组
spring:
cloud:
nacos:
discovery:
group: group_local
六、Hystrix
1.基于Netflix Hystrix二次开发的服务容错保护组件。
目标是对访问远程系统、服务、第三方库的节点的控制,对延迟和故障提供容错能力。Hystrix具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并、服务监控等功能。
2.Command属性
主要用来控制HystrixCommand命令的行为。
execution配置,主要控制HystrixCommand.run()的执行。
#隔离策略,THREAD和SEMAPHORE
hystrix.command.default.execution.isolation.strategy = THREAD
#超时时间,单位ms
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 1000
#是否启动超时时间
hystrix.command.default.execution.timeout.enabled = true
#如果超时是否将它中断
hystrix.command.default.execution.isolation.thread.interruptOnTimeout = true
#执行被取消时是否将它中断
hystrix.command.default.execution.isolation.thread.interruptOnCancel = true
#隔离策略是信号量时,最大并发量
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequest = 10
fallback配置,主要控制HystrixCommand.getFallback()的执行。
circuitBreaker配置
metrics配置
requestContext配置
3.collapser属性
hystrix.collapser.default.maxRequestsInBatch =
hystrix.collapser.default.requestCache.enabled = true
hystrix.collapser.default.requestCache.timerDelayInMilliseconds = 10
4.threadPool属性
hystrix.threadPool.default.coreSize = 10
hystrix.threadPool.default.maxQueueSize = -1
七、Zuul
1.基于Netflix Zuul二次开发的API网关治理组件。
微服务架构的门面Facade,所有外部请求都需要经过网关的过滤校验(签名、登录、自定义校验逻辑)、路由转发,同时网关提供熔断机制、健康检查等功能。
2.API网关应用程序启用Zuul注解
public class Application{
public static void main(String[] args){
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
}
3.面向服务的路由
Zuul与Eureka整合,通过Eureka完成服务列表的自动化维护。
Zuul只映射到具体的服务实例,具体的url交给Eureka的服务发现机制自动维护,只维护path与服务实例的映射组合,不维护每个路由path与具体url的映射关系。
zuul.routes.<routekey>.path = /self-context-path/**
zuul.routes.<routekey>.serviceId = <@FeignClient>
4.请求过滤
安全校验、登录的权限控制等与具体业务无关的非业务逻辑,简化微服务中冗余的拦截器和过滤器。Zuul允许开发者自定义ZuulFilter实现拦截与过滤。
ZuulFilter接口4个核心方法
//过滤器类型,描述Http请求中的各个阶段
String filterType();
//过滤器执行顺序
int filterOrder();
//过滤器是否需要执行
boolean shouldFilter();
//过滤器执行的核心逻辑
Object run();
自定义ZuulFilter核心代码经典实现:
public class AccessFilter extends ZuulFilter{
public Object run(){
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
Object accessToken = request.getParameter("accessToken");
if(null == accessToken){
ctx.setSendZuulResponse(false);
ctx.setSendZuulStatusCode(401);
return null;
}
return null;
}
}
Zuul默认实现的核心过滤器,主要分为post、pre、route三大类
#定义在org.springframework.cloud.netflix.zuul.filters包
ServletDetectionFilter最新被执行的过滤器,判断是Spring的DispatcherServlet处理运行,还是ZuulServlet处理运行
ErrorFilter
八、Sleuth
1.分布式服务跟踪组件。
2.SpringCloud Sleuth应用
只需增加Maven依赖即可
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
3.SpringCloud Sleuth分布式跟踪原理
核心是Trace ID和Span ID。
框架层为每一个请求创建一个全局唯一的跟踪标识Trace ID,同时可以自动在分布式系统中流转,将所有请求过程的日志关联在一起。
框架层为每一个请求都创建一个应用内唯一的跟踪标识Span ID,记录时间戳,统计各单元的逻辑处理时间开销。
4.整合Logstash做分布式日志记录
整合ELK,实际就是整合Logstash。
<dependency>
<group>net.logstash.logback</group>
<artifactId>logstash-Logback-encoder</artifactId>
</dependency>
Logstash负责日志的过滤、收集、存储。
SpringBoot默认使用logback记录日志。
Logstash对logback有支持,因此只需为Logstash准备JSON格式的日志输出即可。
直接通过在logback配置中增加一个对Logstash的Appender,非常方便将日志转换成JSON格式存储和输出。
5.整合Zipkin做分布式耗时监控统计
Zipkin服务端,数据默认仅仅存储在内存中。
<!-- 基本配置 -->
<dependency>
<group>io.zipkin.java</group>
<artifactId>zipkin-server</artifactId>
</dependency>
<dependency>
<group>io.zipkin.java</group>
<artifactId>zipkin-autoconfigure-ui</artifactId>
</dependency>
<!-- 扩展支持收集消息中间件跟踪信息 -->
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
</dependency>
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
Zipkin服务端主类
public class Application{
public static void main(String[] args){
SpringApplication.run(Application.class, args);
}
}
Zipkin客户端
<!-- 基本配置 -->
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-sleuth-zipkin</artifactId>
</dependency>
<!-- 扩展支持收集消息中间件跟踪信息 -->
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-sleuth-stream</artifactId>
</dependency>
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
Zipkin客户端配置
spring.zipkin.base-url = http://zipkin-server:9411
其它类似开源产品pinpointcut、skywalking等。
九、Config
1.分布式配置中心组件。
2.默认采用Git存储配置信息,也支持SVN等其它方式存储。
十、Bus
1.消息总线组件。实际是对Stream组件的高级封装。
2.消息代理
Message Broker是一种消息验证、传输、路由的架构模式,用来解耦通信过程,是一个中间件产品,核心是消息的路由程序。
开源产品
ActiveMQ
RabbitMQ
Kafka
RocketMQ
3.整合SpringBoot、RabbitMQ、SpringCloud Bus
RabbitMQ配置
#rabbitmq基本配置
spring.rabbitmq.host = 192.168.100.1
spring.rabbitmq.port = 5672
spring.rabbitmq.username = dev
spring.rabbitmq.password = dev
spring.rabbitmq.virtual-host = dev-virtual
#rabbitmq异常处理
spring.rabbitmq.listener.direct.retry.enabled = true
spring.rabbitmq.listener.direct.retry.max-attempts = 5
spring.rabbitmq.listener.direct.retry.initial-interval = 2000
spring.rabbitmq.listener.direct.retry.multiplier = 2
spring.rabbitmq.listener.simple.retry.max-interval = 10000
spring.rabbitmq.listener.simple.acknowledge-mode = manual
增加SpringCloud Bus的Maven依赖
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
4.整合SpringBoot、Kafka、SpringCloud Bus
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-starter-bus-kafka</artifactId>
</dependency>
5.SpringCloud Bus应用
事件驱动模型
Spring的事件驱动模型:事件、事件发布者、事件监听者
ApplicationEvent
ApplicationListener
ApplicationEventPublisher
SpringCloudBus事件(继承Spring的事件驱动模型)
RemoteApplicationEvent
RefreshListener/EnvironmentChangeListener/TraceListener
消息总线相关配置
#开启事件跟踪
spring.cloud.bus.trace.enabled = true
#应用是否要连接到消息总线
spring.cloud.bus.enabled = true
#消息总线使用的队列或主题
spring.cloud.bus.destination =
十一、Stream
1.消息驱动组件。
通过发布-订阅模式,以Topic主题方式对外广播。
2.整合SpringBoot、RabbitMQ、SpringCloud Stream
RabbitMQ配置
#公共配置
spring.cloud.stream.rabbit.binder.<key> =
#消费者配置
spring.cloud.stream.rabbit.bindings.<channelName>.consumer.<key> =
#生产者配置
spring.cloud.stream.rabbit.bindings.<channelName>.producer.<key> =
增加SpringCloud Stream的Maven依赖
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
<dependency>
<group>org.springframework.cloud</group>
<artifactId>spring-cloud-starter-binder-rabbit</artifactId>
</dependency>
3.整合SpringBoot、Kafka、SpringCloud Stream
Kafka配置
#公共配置
spring.cloud.stream.kafka.binder.<key> =
#消费者配置
spring.cloud.stream.kafka.bindings.<channelName>.consumer.<key> =
#生产者配置
spring.cloud.stream.kafka.bindings.<channelName>.producer.<key> =
4.消费组、消费分区
确保同一组服务器中只有一个可以消费。
十二、补充内容
1.简单的Restful API
@RestController
public class HealthCheckController{
@GetMapping("/healthCheck")
public String heart(){
return "OK";
}
}
2.启动SpringBoot应用程序
java -jar QRCodePay.jar
3.原生端点actuator
仅仅需要增加如下Maven依赖
<dependency>
<group>org.springframework.boot</group>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
服务启动时会输出很多日志,actuator主要提供常规的微服务管理端点,分为应用配置类、度量指标类、操作控制类的能力,具体功能使用的效果需要自己去开发中体验。