主要组件分工
消费者:
Rbbion:负载均衡,响应超时,重试
Hystrix:降级、熔断、依赖隔离、异步任务、请求合并
Fegin:拟RPC接口调用,整合rbbion+hystrix
注册中心:
Eruka:AP分布式注册中心
网关:
Zuul:基于Servlet实现的网关,整合rbbion+hystrix
Getway:
配置中心:
Config:
hystrix-dashboard turbine 多个同名线程池,在dashboard会合成一个显示,Pool Size是所有池总和
文章图片
当前启动两个微服务,都有@FeignClient(name = "sc-data-service"),设置每个线程池默认大小是10,在dashboard只显示一个sc-data-service,但是Pool Size为两个总和。经测试实际使用中也是各用各的互不干扰。Pool Size初始为0,会随着使用增长,但是不会超过服务设置的max值总和。
依赖隔离ThreadPool命名规则:
Feign:以他的name属性命名,一个FeignClient对应一个pool
【java|Spring Cloud 随记】Hystrix:可以配置ThreadPoolkey,其默认为GroupKey=类名。一个ThreadPoolkey对应一个pool。可以为类/方法单独制定ThreadPoolkey
hystrix启动线程隔离后,ThreadLocal会受影响。
在涉及到hystrix线程尽量避免使用ThreadLocal或将ThreadLocal作为请求传参传递。
使用信号量模式,或是HystrixConcurrencyStrategy解决
Spring Cloud Fegin/RestTemplate组件之间转发http,默认是没有请求头head内容的(cookie也是放在请求头中)
调用方可以添加Fegin拦截器或RestTemplate拦截器,分别实现RequestInterceptor或ClientHttpRequestInterceptor。拦截器在调用方发出http请求时拦截,此时可以为调用请求添加请求头信息再发送到下游服务方。
Spring Cloud Zuul转发http,可将有用信息放在请求头,如用户真实IP
a.zuul转发时注意敏感头设置
zuul转发时注意敏感头设置,application.properties文件中添加 zuul.sensitive-headers=。 sensitiveHeaders的默认值初始值是"Cookie", "Set-Cookie", "Authorization"这三项,可以看到Cookie被列为了敏感信息,所以不会放到新http-head中转发
b.zuul网关添加过滤器,把真实IP放入请求头head中转发:
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
@Component
public class XForwardedForFilter extends ZuulFilter {
private static final String HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR";
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String remoteAddr = request.getRemoteAddr();
//两种方法都可以 为转发的http请求添加head信息
ctx.getZuulRequestHeaders().put(HTTP_X_FORWARDED_FOR, remoteAddr);
ctx.addZuulRequestHeader("USER_HEADER", "USER_HEADER");
return null;
}@Override
public boolean shouldFilter() {
return true;
}@Override
public String filterType() {
return "pre";
}@Override
public int filterOrder() {
return 0;
}
}
收到转发的微服务获取ip:
String ip = request.getHeader("HTTP_X_FORWARDED_FOR");
Zuul过滤器之间传递信息
见上边代码,zuul过滤器之间不能通过参数传递信息,但是提供了 RequestContext类通过ThreadLocal来传递信息。
requestContext.set("startTime", System.currentTimeMillis());
zuul个从 接收用户请求+过滤+转发到微服务+接收微服务响应信息+返回给用户,这整个过程中每个请求对应同一个的线程完成。所以ThreadLocal可以完整的串联整个接收转发响应的全部生命周期。
Zuul+SpringSecurty 验证用户登录简单案例
将认证用户的相关信息放入header中, 后端服务可以直接读取使用
@Component
public class UserInfoHeaderFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.PRE_TYPE;
}@Override
public int filterOrder() {
return FORM_BODY_WRAPPER_FILTER_ORDER - 1;
}@Override
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
//判断上游Filter传递信息
return (boolean ) ctx.get("login");
}@Override
public Object run() {
//取出Authentication
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
RequestContext ctx = RequestContext.getCurrentContext();
//验证不为空 且 不是匿名authentication
if (authentication != null && !(authentication instanceof AnonymousAuthenticationToken)) {
Object principal = authentication.getPrincipal();
String userInfo;
if (principal instanceof SysUser) {
SysUser user = (SysUser) principal;
userInfo = user.getUsername();
} else {
//jwt的token只有name
userInfo = authentication.getName();
}//将认证用户的相关信息放入header中, 后端服务可以直接读取使用
ctx.addZuulRequestHeader(SecurityConstants.USER_HEADER, userInfo);
ctx.addZuulRequestHeader(SecurityConstants.ROLE_HEADER, CollectionUtil.join(authentication.getAuthorities(), ","));
}
else{
//禁止路由
ctx.setSendZuulResponse(false);
]
ctx.setResponeseBody("{\"status\":500,\"messgae\":\"需登录!\"}");
//向下游Filter传递信息
ctx.set("login",false);
}
return null;
}
}
计算Hystrix线程池数量和响应超时
公式:线程数= 消费者每秒一共发送多少请求数/ 单个线程每秒处理请求数 +缓冲线程数
缓冲线程 为处理不确定因素,比如:网络消耗、某个请求用时过长
响应超时:要依据平均请求处理时间,且Hystrix的超时不小于rbbion的 超时*重试次数总用时。否则不会触发重试,直接服务降级。
服务优雅下线 /actuator/service-registry
management:
endpoints:
web:
exposure:
include: service-registry
发送POST请求到
/actuator/service-registry
端点。该应用在Eureka Server上的状被标记为DOWN
,但是应用本身其实依然是可以正常对外服务的。Spring Cloud Config 服务端修改端口
默认端口8888,若想修改端口必须放在bootstrap.yml中,否则无效。bootstrap是boot就先加载的配置文件
转载于:https://www.cnblogs.com/sw008/p/11054315.html
推荐阅读
- java|Spring Boot 学习随记
- java|《Spring Boot 实战》随记
- 一套互联网公司理想架构,建议收藏。。。
- JavaWeb|一篇学会HttpServletRequest
- JavaWeb|Servlet----ServletContext
- JavaWeb|HttpServlet源码分析
- JavaWeb|使用IDEA开发Servlet程序
- JavaWeb|Servlet对象的生命周期
- JavaWeb|适配器(GenericServlet)改造Servlet