spring-cload的基本使用(二)

本文主要讲了

  • 使用Hystix实现服务降级
  • Hystix服务熔断
  • 使用Feign包装请求路径
  • Zuul网关的使用

1、使用Hystix实现服务降级

  • 添加依赖

    org.springframework.cloud
    spring-cloud-starter-netflix-hystrix
  • 添加注解  @EnableCircuitBreaker

这个时候,因为一个springcloud消费方一般都会有下面的三个注解,因此可以使用一个代替   即@SpringCloudApplication

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
  • 服务降级方法,这个方法可以写在方法上,也可以写在类上面

(一),降级方法写在方法上面,这个时候降级方法,必须降级方法,必须跟方法的返回值和参数一致

@RequestMapping("/{id}")
@HystrixCommand(fallbackMethod = "defaultMethod")
public User queryById(@PathVariable("id") long id) {
}
 public User defaultMethod(long id) {
        User user = new User();
        user.setUserName("服务器拥挤");
        user.setUserCode("4525");
        user.setDetail("hahahahhaha");
        return user;
    }

(二)降级方法写在类上

在类上面添加注解

@DefaultProperties(defaultFallback = "defaultMethod")

在方法添加注解

  @HystrixCommand

编写降级方法,降级方法不能有任何参数,但是返回值必须与上面的方法返回值一样

   public User defaultMethod() {
        User user = new User();
        user.setUserName("服务器忙");
        return user;
    }
  • 更改超时时间,在yml文件中配置
hystrix:
  command:
    default:
        execution:
          isolation:
            thread:
              timeoutInMillisecond: 6000 # 设置hystrix的超时时间为6000ms
  • 假如指向对某一个方法配置超时时长,可以直接在方法上配置,这个配置比在yml文件上优先级高
  @RequestMapping("/{id}")
    //@HystrixCommand(fallbackMethod = "defaultMethod")
    @HystrixCommand(commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000")
    })
    public User queryById(@PathVariable("id") long id) {

2、Hystix服务熔断

当服务,一段时间内的请求进入到降级方法的百分比到达一定比例,就会打开服务熔断,这个时候,请求过来,将不在发送请求,而是直接执行降级方法,然后熔断器会开始一段时间,一段时间后,熔断器会尝试请求一定服务,如果这个时候,执行降级方法的百分比还是到达一定比例,将会继续打开熔断器,否则熔断器关闭,服务正常访问,为了方便测试效果可以下面的三个参数进行重新,一般默认就行

这三个参数分别是,统计的次数,熔断器打开的时间,统计进入降级方法的百分比

 @HystrixCommand(commandProperties = {
            @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),
            @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),
            @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="60")
    })

    public User queryById(@PathVariable("id") long id) {

3、使用Feign包装请求路径

  • 引依赖

    org.springframework.cloud
    spring-cloud-starter-openfeign
  • 启动类上面加入注解

@EnableFeignClients // 开启Feign功能
  • 将请求路径包装成一个接口,类似于spring mvc那样

@FeignClient("user-service")
public interface UserFeignClient {

    @GetMapping("/user/{id}")
    User queryUserById(@PathVariable("id") Long id);
}
  • 将这个类注入到需要使用的地方,Feign已经帮我们实现了 RestTemplate 和 负载均衡和重试机制,因此我们不需要配置只需要使用就行

  • Feign对Hystix的支持,若想使用,则需要

(一)。在yml文件中将Hystix的支持打开

feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能

(二)。实现Feign对请求路径包装的接口类,注意这个类,要交给sping来管理

@Component
public class UserClientImpl implements UserClient {
    @Override
    public User queryUserById(Long id) {
        User user = new User();
        user.setUserName("服务器忙");
        return user;
    }
}

(三)将上面的实现类,配置到接口类上

@FeignClient(value = "user-service",fallback = UserClientImpl.class)
  • Feign的其他功能,支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。

(一),压缩是否开启

feign:
  compression:
    request:
      enabled: true # 开启请求压缩
    response:
      enabled: true # 开启响应压缩

(二),压缩参数配置

feign:
  compression:
    request:
      enabled: true # 开启请求压缩
      mime-types: text/html,application/xml,application/json # 设置压缩的数据类型
      min-request-size: 2048 # 设置触发压缩的大小下限

4、Zuul网关的使用

因为我们服务接口默认是对外暴露的,若是让用户直接访问,会有一定得风险,但是如果为每一个服务加上权限验证又过于复杂,因此我们需要使用Zuul,Zuul的作用,是用户所有的请求全部拦截到Zuul,然后Zuul根据访问路径,来决定调用那一个服务

  • 新建一个项目,并引入zuul的坐标,因为zuul最好配合eureka一块使用,这样才能,实现负载均衡,而不是将服务路径写死,因此也需要eureka客户端
     
            org.springframework.cloud
            spring-cloud-starter-netflix-zuul
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
  • 配置启动类
@SpringBootApplication
@EnableZuulProxy // 开启Zuul的网关功能
public class ZuulDemoApplication {

	public static void main(String[] args) {
		SpringApplication.run(ZuulDemoApplication.class, args);
	}
}
  • 配置yml文件
server:
  port: 10000
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka,http://127.0.0.1:10010/eureka
spring:
  application:
    name: zuulGetWay
zuul:
  routes:
    user-service: # 这里是路由id,随意写
      path: /user-service/** # 这里是映射路径
      serviceId: user-service # 指定服务名称 ,如果不使用eureka可以将路径配置成下面形式
      # url: http://127.0.0.1:8001 # 映射路径对应的实际url地址

 

  • 上面的配置由于太常见,因此zuul对注册中心里面的所有服务全部按照上面的规则注册了一遍,因此上面的

zuul规则可以不写,按照默认规则,所有的访问路径就是类似于下面这样

http:// + zuul的ip和端口号 + 服务id + 具体的拦截路径 + 参数

http://localhost:12306/consumer-service/cunsumer/2

如果我们不想这么麻烦的访问,只想直接http://localhost:12306/cunsumer/2就访问到具体的方法,我们进行如下配置

zuul:
  routes:
    consumer-service: # 这里是路由id,随意写
      path: /consumer/** # 这里是映射路径
      serviceId: consumer-service # 指定服务名称
      strip-prefix: false # 即映射路径里面的consumer也作为访问路径
  • 因为zuul会默认为所有的服务都配置访问路径,但是对于一些服务我们并不想暴露出去,因此可以使用下面配置进行屏蔽

zuul:
  ignored-services:
    -user-service
  • zuul的拦截器

 

@Component
public class LoginFilter extends ZuulFilter {
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() {
        //获取上下文
        RequestContext ctx = RequestContext.getCurrentContext();
        //获取request
        HttpServletRequest request = ctx.getRequest();
        //获取请求参数
        String token = request.getParameter("access-token");
        //判断是否存在
        if(TextUtils.isBlank(token)){
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(HttpStatus.FORBIDDEN.value());
        }
        return null;
}

 

你可能感兴趣的:(spring)