Feign:负载均衡器--优雅的解决了客户端用户集群和参数拼接的问题;
Hystrix:熔断器--设置熔断,启动托底数据,防止雪崩问题(一个节点出错,引起整个系统出错);
zuul:网关--用于接口过滤,校验,熔断,可以混淆请求,微服务所有的请求都要向zuul网关发送;
Feign底层默认集成了ribbon和hystrix功能极为强大
微服务集成feign步骤:
1.导入依赖;
2.启动类加注解;(value="这里用来填加了@FeignClient的注解的全路径")
3.编写FeignClient的接口;
4.接口编写完后直接 注入controller 调用方法即可;
1.导入依赖;
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.启动类加注解;(value="这里用来填加了@FeignClient的注解的全路径")
@EnableFeignClients(value = "cn.itsource.FeignPay")
3.编写FeignClient的接口;
//@FeignClient(value = "user-server",fallback = FeignFallBackPay.class) @FeignClient(value = "user-server",fallbackFactory = FeignFactoryFallBack.class) public interface FeignPay { @GetMapping("/user/getUserById/{id}") public User getUserById(@PathVariable("id")Long id); }
4.接口编写完后直接 注入controller 调用方法即可;
@RequestMapping("/pay") @RestController public class PayContrpller { @Autowired private FeignPay feignPay; @GetMapping("/getUserById/{id}") public User getUserById(@PathVariable("id")Long id){ User user = feignPay.getUserById(id); return user; } }
集成Feign所需要用到的注解 :
1.@EnableFeignClients(value = "cn.itsource.FeignPay")//用在启动类上value="这里用来填加了@FeignClient的注解的全路径"
2.
@FeignClient(value = "user-server",fallbackFactory = FeignFactoryFallBack.class)用在用了feignclient的接口上,接口和目标方法保持一致;
3.
@EnableCircuitBreaker//开启熔断支持feign集成了hystrix,启用注解开启熔断支持;
feign:设置托底数据有两种方法: 第二种方法:可以打印错误信息到控制台
第一种方法:
@Component public class FeignFallBackPay implements FeignPay{ @Override public User getUserById(Long id) { return new User(id,"这个是feign里面的托底数据",null); } }
第二种方法:
@Component public class FeignFactoryFallBack implements FallbackFactory<FeignPay> { @Override public FeignPay create(Throwable throwable) { throwable.printStackTrace();//打印错误信息 return new FeignPay() { @Override public User getUserById(Long id) { return new User(id,"这是Fegin里面的托底数据",null); } }; } }
Hystrix:熔断器 工作原理:(重点)
hystrix:在ribbon环境中使用步骤:
1.导入依赖:
2.启动类添加注解:
3.目标方法上加注解 注解里的参数值和托底数据保持一致;
4.设置托底方法:
1.导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2.启动类添加注解:
@EnableCircuitBreaker//开启熔断支持
3.目标方法上加注解 注解里的参数值和托底数据保持一致;
@GetMapping("/getUserById/{id}")
@HystrixCommand(fallbackMethod = "fallbackMethod")
public User getUserById(@PathVariable("id")Long id){
String url = "http://user-server/user/getUserById/"+id;
ResponseEntity<User> forEntity = restTemplate.getForEntity(url, User.class);
return forEntity.getBody();
}
4.设置托底方法:
public User fallbackMethod(@PathVariable("id")Long id){ return new User(1l,"这个是ribbon里的托底数据",null); }
hystrix所需要用的注解
1.@EnableCircuitBreaker//开启熔断支持
2.@HystrixCommand(fallbackMethod = "fallbackMethod")
zuul可以动态的进行路由分发;本质是一个webServlet应用(过滤器);
在微服务架构里,所有的请求都要打入微服务,登录校验会很麻烦,所以zuul出现了,完美优雅的解决了这些问题;
在微服务中集成zuul;
1.导入依赖
2.配置yml(重要)
3.启动类加注解
1.导入依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency>
2.配置yml(重要)
zuul: prefix: "/servers" #统一访问前缀 ignoredServices: "*" #禁用掉使用浏览器通过服务名的方式访问服务 routes: pay-server: "/pay/**" #指定pay-server这个服务使用 /pay路径来访问 - 别名 order-server: "/order/**" #指定order-server这个服务使用 /order路径来访问
3.启动类加注解
@EnableZuulProxy
用zuul设置简单的登录校验
1.实现zuulFilter
2.交给spring管理
@Component public class LoginFilter extends ZuulFilter { @Override //设置过滤器类型 public String filterType() { return FilterConstants.PRE_TYPE; } @Override //设置过滤器排序 public int filterOrder() { return 0; } @Override public boolean shouldFilter() { //1.获取request请求 //2.判断是否需要过滤 //3.不用直接返回false 反之则返回true //1.获取request请求 RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); //2.判断是否需要过滤 String requestURI = request.getRequestURI(); //3.看是否需要过滤 if(requestURI.contains("/login")){ return false; } return true; } @Override //shouldFilter返回值为true才执行run方法 public Object run() throws ZuulException { //1.从请求头中获取token RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); HttpServletResponse response = currentContext.getResponse(); //2.根据token判断是否登录过 String token = request.getHeader("token"); //3.没有token则返回错误信息 if(!StringUtils.hasLength(token)){ response.setContentType("application/json;charset=utf-8"); try { PrintWriter writer = response.getWriter(); writer.write("没有token,请您登录!"); } catch (IOException e) { e.printStackTrace(); }//结束方法 currentContext.setSendZuulResponse(false); } //4.有token则放行 return null; } }
问题:如果用户通过访问zuul来访问微服务地址,中间微服务接口出错了,则会直接返回错误信息给用户,此时则需要给zuul设置熔断;
1.实现fallbackProvider接口
2.交给spring管理
@Component public class FallBackOrder implements FallbackProvider { @Override public String getRoute() { return "*"; } @Override public ClientHttpResponse fallbackResponse(String route, Throwable cause) { return new ClientHttpResponse(){ @Override public HttpHeaders getHeaders() { HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); return headers; } @Override public ByteArrayInputStream getBody() throws IOException { return new ByteArrayInputStream("暂无可用服务,请稍后再试!!!".getBytes()); } @Override public HttpStatus getStatusCode() throws IOException { return HttpStatus.OK; } @Override public int getRawStatusCode() throws IOException { return 200; } @Override public String getStatusText() throws IOException { return "ok"; } @Override public void close() { } }; } }