eureka注册中心
- eureka注册中心是spring cloud微服务的基石.
- 所有微服务都需要注册到eureka上,提供自己的请求地址给其他注册到eureka上的微服务已发现。
每间隔30s微服务会向eureka发送一次心跳数据,当eureka90s没有收到响应心跳时,会认为该服务不可用,默认不会剔除该服务(可调整) - 和zookeeper比较,zookeeper注重数据的一致性,而eureka更注重系统的可用性
- application.yml简单配置
application.name=eureka
server.port=2001
defaultZone=http://localhost:2001/eureka
ribbon负载均衡和重试
- 单独使用 ribbon,开启重试需要自己写代码,添加重试参数配置
后面 ribbon 被 feign 和 zuul 封装,不做任何配置,不写任何代码,可以
直接使用负载均衡和重试 - 简单代码演示
- 负载均衡
@LoadBalanced //负载均衡注解
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
- 重试添加 spring-retry 依赖
ribbon:
MaxAutoRetriesNextServer: 2 #更换实例的次数
MaxAutoRetries: 1 #当前实例重试次数,尝试失败会更换下一个实例
OkToRetryOnAllOperations: true #默认只对GET请求重试, 当设置为true时, 对POST等所有类型请求都重试
代码
@LoadBalanced
@Bean
public RestTemplate getRestTemplate() {
SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
f.setConnectTimeout(1000);
f.setReadTimeout(1000);
return new RestTemplate(f);
}
hystrix断路器 降级和熔断
- 降级:
当服务不可用,或者访问超时,可以执行降级代码,可以返回错误信息,或者返回缓存数据 - 熔断:
10秒内请求数量达到20个,并且,有50% 出现失败降级的情况,会打开断路器,所有的请求,都直接降级,不再向后台微服务转发
断路器打开5秒后,会处于半开状态,当请求到达时,会尝试向后台符转发,如果成功,会关闭断路器,如果仍然失败,保持打开状态
Hystrix dashboard 仪表盘
图形化展示各个请求的情况
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
暴露 hystrix.stream 监控端点
management:
endpoints:
web:
exposure:
include: hystrix.stream
访问hystrix微服务
http://localhost:4001/hystrix
填入 hystrix 的监控端点,开启监控
http://localhost:3001/actuator/hystrix.stream
feign 声明式客户端,只定义远程调用接口
- 整合 ribbon 和 部分hystrix
- 默认启用负载均衡和重试
- 启用 hystrix: yml文件中添加配置 feign.hystrix.enabled=true
@FeignClient(name="服务id", fallback=XxxFB.class)//降级实现类,建议(接口名+FB)结尾
interface A {
@GetMapping("/xxxx")
JsonResult f(@RequestParameter String name);
}
zuul API网关
spring cloud 对外的统一大门,提供统一的调用入口,所有的系统请求都需要经过zuul的拦截过滤
- yml路径配置,当微服务名和请求路径前缀一致时可不配置
zuul:
routes:
item-service: /item-service/**
user-service: /user-service/**
order-service: /order-service/**
依然默认启用负载均衡,不过重试需要添加spring-retry依赖
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>
并yml中配置重试参数启动
zuul:
retryable: true
ribbon:
ConnectTimeout: 1000
ReadTimeout: 1000
MaxAutoRetriesNextServer: 1
MaxAutoRetries: 1
-
zuul + hystrix 降级
-
需要实现FallbackProvider 接口,并在方法getRoute() 中指定应用此降级类的服务id,星号或null值可以通配所有服务
-
定义过滤器,需要继承 ZuulFilter
package cn.tedu.sp11.filter;
import javax.servlet.http.HttpServletRequest;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import cn.tedu.web.util.JsonResult;
@Component
public class AccessFilter extends ZuulFilter{
@Override
public boolean shouldFilter() {
//对指定的serviceid过滤,如果要过滤所有服务,直接返回 true
RequestContext ctx = RequestContext.getCurrentContext();
String serviceId = (String) ctx.get(FilterConstants.SERVICE_ID_KEY);
if(serviceId.equals("item-service")) {
return true;
}
return false;
}
@Override
public Object run() throws ZuulException {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest req = ctx.getRequest();
String token = req.getParameter("token");
if (token == null) {
//此设置会阻止请求被路由到后台微服务
ctx.setSendZuulResponse(false);
//向客户端的响应
ctx.setResponseStatusCode(200);
ctx.setResponseBody(JsonResult.err().code(JsonResult.NOT_LOGIN).toString());
}
//zuul过滤器返回的数据设计为以后扩展使用,
//目前该返回值没有被使用
return null;
}
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}
@Override
public int filterOrder() {
//该过滤器顺序要 > 5,才能得到 serviceid
return FilterConstants.PRE_DECORATION_FILTER_ORDER+1;
}
}
- zuul + hystrix 数据监控
- zuul中已经包含 actuator 依赖,所以只需要暴露 hystrix.stream 监控端点即可
management:
endpoints:
web:
exposure:
include: hystrix.stream
turbine 聚合监控
hystrix dashboard 一次只能监控一个服务实例,使用 turbine 可以汇集监控信息,将聚合后的信息提供给 hystrix dashboard 来集中展示和监控
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
turbine:
app-config: zuul
cluster-name-expression: new String("default")
sleuth 链路跟踪及zipkin 链路分析
随着系统规模越来越大,微服务之间调用关系变得错综复杂,一条调用链路中可能调用多个微服务,任何一个微服务不可用都可能造整个调用过程失败
sleuth 可以跟踪调用链路,分析链路中每个节点的执行情况
添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>
此时通过zull网关,在微服务的控制台日志中,可以看到以下信息:
[服务id,请求id,span id,是否发送到zipkin]
- 请求id:请求到达第一个微服务时生成一个请求id,该id在调用链路中会一直向后面的微服务传递
- span id:链路中每一步微服务调用,都生成一个新的id
[zuul,6c24c0a7a8e7281a,6c24c0a7a8e7281a,false]
[order-service,6c24c0a7a8e7281a,993f53408ab7b6e3,false]
[item-service,6c24c0a7a8e7281a,ce0c820204dbaae1,false]
[user-service,6c24c0a7a8e7281a,fdd1e177f72d667b,false]
zipkin 可以收集链路跟踪数据,提供可视化的链路分析
下载 zipkin 服务器
启动 zipkin 时,连接到 rabbitmq
java -jar zipkin-server-2.12.9-exec.jar --zipkin.collector.rabbitmq.uri=amqp://admin:admin@192.168.64.140:5672
访问zipkin服务器
在微服务中添加zipkin 起步依赖
- 如果没有配置过 spring cloud bus,还需要添加 rabbitmq 依赖和连接信息
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
链路跟踪数据中,默认只有 10% 会被收集到zipkin,如果没有看到多请求几次就好
参考资料
Spring Cloud入门操作手册