Spring Boot 注解
@GetMapping(“/{id}”)
@SpringBootApplication
组合注解,整合了@Configuration
、@EnableAutoConfiguration
、@ComponentScan
Spring Boot Actuator:提供很多监控端点
添加依赖,就可以通过http://{id}:{port}/{endpoint}
的形式访问这些端点,从而了解应用程序的运行情况。可以查看配置信息、属性列表、线程活动快照、环境变量、健康检查、URL路径、最近100个HTTP请求
Eureka 服务发现组件
SpringCloud提供了多种服务发现组件的支持,例如Eureka、Consul和Zookeeper等,Eureka是Netflix开源的服务发现组件,它包含Server和Client。SpringCloud将它集成在子项目SpringCloud Netflix中,从而实现微服务的注册于发现。
原理
各个微服务启动时向Eureka Server注册自己的信息,Eureka Server会存储这些信息
Eureka Client会周期性(默认30s)地向Eureka Server发送心跳续约自己的在线状态
Eureka Server的实例集群中,相互间通过复杂的方式实现注册表数据的同步
Eureka Client也会缓存Eureka Server中注册的信息,以便快捷完成调用
编写Eureka Server
- 添加依赖
1 | <dependencies> |
@EnableEurekaServer
application.yml
1 | server: |
微服务注册到Eureka Server
- 添加依赖
1 | <dependencies> |
@EnableEurekaClient 或者 @EnableDiscoveryClient
application.yml
1 | spring: |
REST端点
Eureka Server提供了一些REST端点。非JVM的微服务可使用这些REST端点操作Eureka,从而实现注册与发现。事实上,Eureka Client就是使用java编写的操作这些REST端点的类库。Eureka提供的REST端点,可以使用XML或者JSON与这些端点通信,默认是XML。
自我保护模式
当Eureka Server节点在短时间内丢失过多客户端时,节点就会进入自我保护模式。就不再删除服务注册表中的数据。
可以通过多种方式忽略网卡
可以开启eureka的健康检查
Ribbon 实现客户端侧负载均衡
Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP客户端的行为,为Ribbon配置服务提供者地址列表后,Ribbon就可基于某种负载均衡算法,自动帮助服务消费者去请求。
编写
- 添加依赖
1 | <dependencies> |
前面引入的spring-cloud-starter-eureka中包含了ribbon,可以不用再引入
@LoadBalanced 整合负载均衡
可以通过注入LoadBalancerClient来获取当前是哪个节点
可以自定义Ribbon配置
1 | event-chenshinan |
脱离Eureka使用Ribbon
去掉@EnableDiscoveryClient
application.yml中添加
1 | event-chenshinan |
使用Fegin实现声明式REST调用
编写
- 添加依赖
1 | <dependencies> |
@EnableFeginClient 启动类添加
@FeignClient
1 | "event-chenshinan", url="http://localhost:8000/", configuration="FeignConfiguration.class") (name= |
- client接口中的方法需要
@RequestParam("id") Long id
1 | "event-chenshinan") (name= |
自定义Feign配置
手动创建Feign,不用注解和注入的方式
Feign对压缩的支持
1 | feign.compression.request.enabled=true |
开启Feign日志
使用Hystrix实现微服务容错机制
Hystrix是一个实现了超时机制和断路器模式的工具类库
编写
- 添加依赖
1 | <dependencies> |
@EnableCircuitBreaker或EnableHystrix 启动类添加
@HystrixCommand(fallbackMethod=”xxxFallback”) 除了回退方法还有很多属性可以配置
1 | "xxxFallback",commandProperties={ (fallbackMethod= |
注意:当请求失败、被拒绝、超时或者断路器打开时,都会进入回退方法
功能
包裹请求
跳闸机制
资源隔离
监控
回退机制
自我修复
Hystrix线程隔离策略与传播上下文
THREAD(线程隔离)[默认]:使用该方法,HystrixCommand将会在单独的线程上执行,并发请求受线程池中的线程数量限制
SEMAPHORE(信号量隔离):使用该方式,HystrixCommand将会在调用线程上执行,开销较小,并发请求受到信号量个数的限制
Fegin使用Hystrix,默认支持
回调方法
1 | "event-chenshinan",fallback=xxxFallback.class) (name= |
xxxFallback要实现UserFeignClient接口
通过FallbackFactory检查回退原因
1 | "event-chenshinan",fallbackFactory=xxxFallbackFactory.class) (name= |
禁用Hystrix
- 单个禁用 FeignDisableHystrixConfiguration
1 | "event-chenshinan",configuration=FeignDisableHystrixConfiguration.class) (name= |
- 全局禁用,在application.yml
1 | feign: |
监控
使用Turbine聚合监控数据
Turbine是一个聚合Hystrix监控数据的工具,它可将所有相关/hystrix.stream端点的数据聚合到一个组合的/turbine.stream中,从而让集群的监控更加方便
使用Zuul构建微服务网关
微服务网关是介于客户端和服务端之间的中间层,所有外部请求都会先经过微服务网关。Zuul是Netfix开源的微服务网关,Zuul的核心是一系列的过滤器。完成如下功能:身份认证与安全、审查与监控、动态路由、压力测试、负载分配、静态响应处理、多区域弹性。
优点
易于监控
易于认证
减少了客户端与各个微服务之间的交互次数
Zuul使用的默认HTTP客户端是Apache HTTP Client,也可以支持RestClient、OkHttpClient
编写
- 添加依赖
1 | <dependencies> |
@EnableZuulProxy 启动类添加
application.yml
1 | server: |
默认情况下,Zuul会代理所有注册到Eureka Server的微服务,并且Zuul的路径规则如下:http://ZUUL_HOST:ZUUL_PORT/微服务在Eureka上的serviceId/**会被转发到serviceId对应的微服务
路由配置详解
- 自定义指定微服务的访问路径
1 | zuul: |
- 忽略指定微服务
1 | zuul: |
- 同时指定path和URL
1 | zuul: |
这种配置的路由不会作为HystrixCommand执行,同时也不能使用Ribbon来负载均衡多个URL
- 同时指定path和URL,并且不破坏Zuul的Hystrix、Ribbon特性
1 | zuul: |
- 路由前缀
1 | zuul: |
可将com.netflix包的日志级别设为DEBUG,这样有助于理解Zuul的路由配置
1 | logging: |
Zuul的安全与Header
- 为防止某些敏感Header外泄
1 | zuul: |
- 全局指定敏感Header
1 | zuul: |
- 忽略Header
1 | zuul: |
使用Zuul上传文件
对于小文件(1M以内)上传,无须任何处理。对于大文件(10M以上),需要为上传路径添加/zuul前缀。也可以使用zuul.servlet-path自定义前缀。
- 如果Zuul使用了Ribbon做负载均衡,对于超大文件(500M),需要提升超时设置。
设置在gate-way
1 | hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:6000 |
- application.yml设置multipart的文件大小
1 | http: |
Zuul过滤器
过滤类型与请求周期
PRE:这种过滤器在请求被路由之前调用
ROUTING:这种过滤器将请求路由到微服务
POST:这种过滤器在路由到微服务以后执行
ERROR:在其他阶段发送错误时执行该过滤器
自定义过滤类型
编写Zuul过滤器
继承抽象类ZuulFilter实现抽象方法
filterType:返回过滤器类型
filterOrder:指定过滤器的执行顺序
shouldFilter:返回是否执行该过滤器
run:过滤器的具体逻辑
禁用Zuul过滤器
只需设置zuul.<SimpleClassName>.<filterType>.disable=true
容错与退回
Zuul的Hystrix监控的粒度是微服务,而不是某个API。回退的话需要实现ZuulFallbackProvider接口,并指定为哪个微服务提供回退
高可用
Zuul客户端也注册到了Eureka Server上,自动提供多个Zuul节点
Zuul客户端为手机APP等,无法注册到Eureka Server上,需要借助一个额外的负载均衡器来实现Zuul的高可用,例如Nginx、HAProxy等,Zuul客户端将请求发送到负载均衡器,负载均衡器将请求转发到其代理的其中一个Zuul节点上。
使用Zuul聚合微服务
外部请求需要查询Zuul后端的多个微服务,可使用Zuul聚合微服务请求,例如手机APP只需发送一个请求给Zuul,由Zuul请求用户微服务以及电影微服务,并组织好数据给手机APP
使用Spring Cloud Config统一管理服务器配置
Spring Cloud Config为分布式系统外部化配置提供服务器端和客户端的支持,它包括Config Server和Config Client两部分。Config Server是一个可横向扩展、集中式的配置服务器,默认使用Git存储配置内容。Config Client在各个微服务中,各个微服务在启动时,会起球Config Server以获取所需要的配置属性,然后缓存这些属性以提高性能。
特性
集中管理配置
不同环境不同配置
运行期间可动态调整
配置修改后可自动更新
编写Config Server
- 添加依赖
1 | <dependencies> |
@EnableConfigServer 启动类添加
application.yml
1 | server: |
- 可以使用Config Server的端点获取配置文件的内容,映射规则如下:
1 | /{application}/{profile}[/{label}] |
以上端点都可以映射到{application}-{profile}.properties
这个配置文件,{application}表示微服务的名称,{label}对应Git仓库的分支,默认是master
- 通过构造URL的方式,获取了Git仓库中的配置信息
编写Config Client
- 添加依赖
1 | <dependencies> |
- application.yml
1 | spring: |
spring.application.name:对应Config Server所获取的配置文件中的{application}
spring.cloud.config.uri:指定Config Server的地址,默认是http://localhost:8888
spring.cloud.config.profile:profile对应Config Server所获取的配置文件中的{profile}
spring.cloud.config.label:指定Git仓库的分支,对应{label}
注意
以上属性应配置在bootstrap.yml
,而不是application.yml
bootstrap与application
加载顺序:这里主要是说明application和bootstrap的加载顺序。
- bootstrap.yml(bootstrap.properties)先加载
application.yml(application.properties)后加载
bootstrap.yml 用于应用程序上下文的引导阶段。 bootstrap.yml 由父Spring ApplicationContext加载。 父ApplicationContext 被加载到使用 application.yml 的之前。
配置区别
bootstrap.yml 和application.yml 都可以用来配置参数。
- bootstrap.yml 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。
application.yml 可以用来定义应用级别的,如果搭配 spring-cloud-config 使用 application.yml 里面定义的文件可以实现动态替换。
使用Spring Cloud Config Server时,应在 bootstrap.yml 中指定: spring.application.name spring.cloud.config.server.git.uri
注意
一旦bootStrap.yml 被加载,则内容不会被覆盖,即便后期加载的application.yml的内容标签与bootstrap的标签一致,application 也不会覆盖bootstrap,而application.yml 里面的内容可以动态替换。
Git仓库配置详解
占位符支持
模式匹配
搜索目录
启动时加载配置文件
Config Server和Config Client都注册搭配Eureka Server上
将Config Server和Config Client都注册到Eureka Server上,在Config Client的bootstrap.yml配置如下:
1 | spring: |
使用Spring Cloud Sleuth实现微服务跟踪
- 添加依赖
1 | <dependencies> |
- 设置配置
1 | spring: |
可以配合Zipkin使用,Zipkin是Twitter开源的分布式跟踪系统
可以配合Zipkin,再用RabbitMQ收集数据,并把数据存储在Elasticsearch
常见问题总结
Eureka注册服务慢
想要解决服务注册慢的问题,只需将eureka.instance.leaseRenewalIntervalInSeconds
设成一个更小的值。该配置用于设置Eureka Client向Eureka Server发送心跳的时间间隔,默认是30s。在生产环境中,建议坚持使用默认值。
如何自定义微服务的InstanceID
1 | spring: |
Eureka的UNKNOWN问题
一般就是未配置spring.application.name
或者eureka.instance.appname
属性,实例的状态为UNKNOWN可能是由健康检查导致,eureka.client.healthcheck.enabled=true
必须设置在application.yml中,而不能设置在bootstrap.yml中,否则一些场景下回导致应用状态UNKNOWN的问题。
Hystrix/Feign整合Hystrix后首次请求失败
- 延长Hystrix的超时时间
1 | hystrix.command.default.execution.isolation.thread.thomeoutInMilliseconds:5000 |
- 禁用Hystrix的超时
1 | hystrix.command.default.execution.timeout.enabled:false |
- 可以为Feign禁用Hystrix
1 | feign.hystrix.enabled:false |
使用 Docker Compose 编排微服务
使用compose来快速创建并启动多个容器
安装compose
工程、服务、容器
Dokcer Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container),Docker Compose运行目录下的所有文件组成一个工程,一个工程可包含多个服务。
docker-compose.yml常用命令
build:通过指定dockerfile启动容器
environment:环境变量设置
expose:暴露端口,只将端口暴露给连接的服务,而不暴露给宿主机
image:指定镜像名称或镜像ID,如果本地不存在该镜像,Compose会尝试下载该镜像
links:连接到其他服务的容器
ports:暴露端口信息,可使用HOST:CONTAINER的格式,也可只指定容器端口
volumes:卷挂载路径设置
docker-compose常用命令
- build 构建或重新构建服务
1 | docker-compose build |
- help 帮助
1 | docker-compose help build |
- kill 通过发送SIGKILL信号停止服务的容器
1 | docker-compose kill eureka |
logs 查看服务的日志输出
ps 列出所有容器
1 | docker-compose ps |
- scale 设置指定服务运行容器的个数,以service=num的形式指定,单个服务启动多个节点来负载均衡
1 | docker-compose scale user=3 |
- start 启动指定服务已存在的容器
1 | docker-compose start eureka |
- stop 停止已运行的容器
1 | docker-compose stop eureka |
- up 构建、创建、重新创建、启动,连接服务的相关容器
docker-compose up命令会聚合所有容器的输出,当命令退出时,所有容器都会停止。使用-d参数在后台运行
1 | docker-compose up -d |
网络设置
默认情况下,Compose会为应用创建一个网络,服务的每个容器都会加入该网络中。这样,容器就可被该网络中的其他容器访问
更新容器
当服务的配置发生更改时,同样可以用up更新配置,此时Compose会删除旧容器并创建新容器,新容器会以不同的IP地址加入网络。任何指向旧容器的连接都会被关闭,容器会重新找到新容器并连接上去。
网络隔离
A服务与B服务隔离,两者分别使用自己的网络,C服务可以与两者通信。使用networks
命令,即可方便实现服务间的网络隔离与连接
参考文献
- 【SpringCloud和Docker】书籍