SpringCloud入门
- 微服务是一种架构方式,最终需要技术架构去实施。springcloud是一种微服务架构的解决方案,是很多组件的集合
- 主要涉及的组件
Eureka
注册中心,服务注册/发现Zuul
网关组件,提供智能路由,访问过滤 (集成Ribbon Hystrix
)Ribbon
客户端负载均衡Feign
服务调用,给与Ribbon和Hystrix的声明式事务调用组件Hystrix
容错管理组件,实现断路器模式,帮助服务依赖中出现的延迟和为故障提供强大的容错能力
- 通过provider模块和consumer模块的分布式有什么问题
- 在consumer中,url硬编码不方便维护
- consumer需要记忆provider地址,如果变更,得不到通知
- consumer不清楚provider状态,服务器宕机也不知道
- provider只有一台服务,不具备高可用
- 及时provider形成集群,consumer还需要自己实现负载均衡
1. Eureka组件
- 要做的事情
- 引入组件的启动器
- 覆盖默认配置
- 在引导类上添加注解,开启相关组件
- 各种客户端的设置
- 注册中心 : my-eureka
- 引入依赖
spring.application.name=服务名
eureka.client.service-url.defaultZone=
- 引导类上添加
@EnableEurekaServer
- 客户端 : my-service-provider my-service-consumer
- 引入依赖
- 添加配置
3.@EnableDiscoveryClient
DiscoveryClient.getInstances
(启用eureka客户端)
- 注册中心 : my-eureka
2. Ribbon组件
- 负载均衡组件(不需要引入依赖,eureka集成好了)
- 添加
@LoadBalanced
注解,如在引导类中(这里因为之前用到了restTemplate)@Bean @LoadBalanced // 开启负载均衡 public RestTemplate restTemplate(){ return new RestTemplate(); }
- 改发送请求的方式
this.restTemplate.getForObject("http://service-provider/user/" + id,User.class);
3. Hystrix组件
-
熔断管理组件,拦截处理请求路由,也可以做身份验证
-
浏览器访问一个微服务,首先经过Zuul网关看是否有权限,拦截后再分发给不同的微服务,每个微服务都是不同的集群,也需要做负载均衡,zuul最有可能面临高并发压力,也要做熔断,所以也集成了Hystrix。
-
线程隔离,服务降级(检查每次请求是否超时或者连接池已满)
- Hystrix为每个依赖服务调用分配一个小的线程池。如果已满就拒绝调用,默认不排队
- 用户请求通过线程池中的空闲线程来访问服务,如果线程池满或请求超时,就会进行服务降级(优先保证核心服务而非核心服务不可用或弱可用)处理
- 简单使用:
- 引入hystrix启动器
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000
配置,默认是1000ms- 引导类上添加注解
@EnableCircuitBreaker
@SpringCloudApplication
- 定义熔断方法:局部(要和被熔断的方法返回值和参数列表一致) 全局(返回值类型要和被熔断的方法一致,参数为空)
@HystrixCommand(fallbackMethod="局部熔断方法名")
: 声明被熔断的方法@DefaultProperties(defaultFallback="全局熔断方法名")
-
服务熔断(请求都不发了)
- 服务调用方主动熔断(服务反应慢或大量超时),防止整个系统被拖垮
- 弹性容错重连(一段时间后允许部分请求通过,如果成功则回到闭合)
- hystrix状态
close
:闭合状态,所有请求正常访问open
:打开状态,如果在一定时间内,失败的比例不小于50%或者次数不小于20次,所有请求都无法访问了half open
:半开状态,放部分通过
- open状态默认5s休眠期,休眠期内所有请求无法正常访问。5s之后进入half open状态,放部分请求通过,如果正常服务,就会进入close状态,如果不能会继续open状态。
4. feign组件
- feign是Netflix开发的声明式、模板化的HTTP客户端。可以把rest的请求进行隐藏,伪装成类似springMVC的Controller一样,你不用自己拼装url,拼接参数等操作,一切都交给feign去做
- 使用步骤
- 引入
openFeign
启动器(阿里的镜像不全,用spring的引入) - 覆盖默认配置:
feign.hystrix.enable=true
,开启feign的熔断功能 - 在引导类上加
@EnableFeignClients
注解启用feign - 创建一个接口,在接口上添加
@FeignClient(value="服务id",fallback="实现类.class")
- 在接口中定义方法,这些方法的书写方式和之前controller类似
- 创建熔断类,实现feign接口,实现对应的方法,这些方法就是熔断方法(记得添加
@Component
注解)
- 引入
5. Zuul网关组件
- 路由配置使用步骤
- 引入zuul启动器
- 覆盖默认配置:
#第一种 zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.url=http://localhost:8082 #第二种 zuul.routes.<路由名称>.path=/service-provider/** zuul.routes.<路由名称>.serviceId=service-provider #第三种(***) zuul.routes.服务名=/service-provider/** #第四种 不用配置,默认就是服务id开头路径
- @EnableZuulProxy 开启zuul网关
- 过滤器流程
- 正常:pre routing post 响应
pre
或routing
异常:error post 响应error
异常: post 响应post
异常: error 响应
- 过滤器配置使用步骤
- 创建一个类,继承ZuulFilter基类
- 重写四个方法
filterType
: pre route post errorfilterOrder
:返回值越小,优先级越高shouldFilter
:是否执行run方法,true执行run
具体的拦截逻辑
- 过滤器实例
@Component
public class LoginFilter extends ZuulFilter{
@Override
public String filterType(){
return "pre";
}
@Override
public int filterOrder()
{
return 10;
}
@Override
public boolean shouldFilter(){
return true;
}
@Override
public Object run() throws ZuulException{
// 初始化zuul网关的context上下文对象
RequestContext context = RequestContext.getCurrentContext();
//首先获取request对象
HttpServletRequest request = context.getRequest();
// 获取参数
String token = request.getParameter("token");
if (StringUtils.isBlank(token)){
//拦截 不转发请求
context.setSendZuulResponse(false);
//401 身份认证失败
context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
//设置响应提示
context.setResponseBody("request error!");
}
//返回值为null,代表该过滤器什么都不做
return null;
}
}