vlambda博客
学习文章列表

面试复习之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文件

spring.profiles = devspring.application.name = zuul-gateway
server.port = 8080
eureka.client.serviceUrl.defaultZone = 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@SpringBootApplicationpublic 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@SpringBootApplicationpublic 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启用HttpClientfeign.httpclient.enabled = true


5.序列化

    JSON与对象之间转换。


6.请求压缩

feign.compression.request.enabled = truefeign.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和SEMAPHOREhystrix.command.default.execution.isolation.strategy = THREAD#超时时间,单位mshystrix.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 = truehystrix.collapser.default.requestCache.timerDelayInMilliseconds = 10


4.threadPool属性

#设置执行命令线程池的核心线程数,命令最大并发数hystrix.threadPool.default.coreSize = 10
#线程池的队列容量hystrix.threadPool.default.maxQueueSize = -1
#等等,类似Dubbo框架的基本都有


七、Zuul

1.基于Netflix Zuul二次开发的API网关治理组件。

    微服务架构的门面Facade,所有外部请求都需要经过网关的过滤校验(签名、登录、自定义校验逻辑)、路由转发,同时网关提供熔断机制、健康检查等功能。


2.API网关应用程序启用Zuul注解

@EnableZuulProxy@SpringCloudApplicationpublic 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服务端主类

@EnableZipkinServer@SpringCloudApplicationpublic 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是一种消息验证、传输、路由的架构模式,用来解耦通信过程,是一个中间件产品,核心是消息的路由程序。

    开源产品

ActiveMQRabbitMQKafkaRocketMQ


3.整合SpringBoot、RabbitMQ、SpringCloud Bus

    RabbitMQ配置

#rabbitmq基本配置spring.rabbitmq.host = 192.168.100.1spring.rabbitmq.port = 5672spring.rabbitmq.username = devspring.rabbitmq.password = devspring.rabbitmq.virtual-host = dev-virtual
#rabbitmq异常处理spring.rabbitmq.listener.direct.retry.enabled = truespring.rabbitmq.listener.direct.retry.max-attempts = 5spring.rabbitmq.listener.direct.retry.initial-interval = 2000spring.rabbitmq.listener.direct.retry.multiplier = 2
spring.rabbitmq.listener.simple.retry.max-interval = 10000spring.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

@RestControllerpublic 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主要提供常规的微服务管理端点,分为应用配置类、度量指标类、操作控制类的能力,具体功能使用的效果需要自己去开发中体验。