• springCloud


    1.Hystrix

    Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败。

    服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应

    1.1.线程隔离,服务降级

    Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队.加速失败判定时间。

    用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理。

    降级处理:优先保证核心服务,而非核心服务不可用或弱可用

    用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果(例如返回友好的提示信息) 。

    服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。

    触发Hystix服务降级的情况:

    • 线程池已满
    • 请求超时

    1.2.使用Hystrix

    1.2.1.引入Hystrix依赖 (下面所有的代码基于上一篇:spirngCloud-Eureka写的)
    链接地址:https://www.cnblogs.com/cqyp/p/13284109.html
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    
    1.2.2.开启熔断
    @SpringBootApplication
    @EnableDiscoveryClient //启动客户端
    @EnableCircuitBreaker   //开启熔断
    public class ServiceConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(ServiceConsumerApplication.class,args);
        }
    }
    

    注: 这三个注解可以由一个组合注解代替:@springCloudApplication。

    1.2.3.使用熔断

    • 在对应的方法上加@HystrixCommand 注解,为熔断方法
    • 定义熔断的方法
    @Controller
    @RequestMapping("consumer/user")
    public class UserController {
        @Autowired
        private UserClient userClient;
        @GetMapping
        @ResponseBody
        @HystrixCommand(fallbackMethod = "queryUserByIdFallBack") //声明熔断方法
        public String queryUserById(@RequestParam("id") Integer id) {
            return this.userClient.queryUserById(id).toString();
        }
    
         //定义熔断方法,和被熔断方法的返回值一样
        public String queryUserByIdFallBack() {
            return "服务正忙,请稍后再试";
    
        }
      }
    

    定义全局熔断方法:每个方法熔断都会执行FallbackMethod此方法

    @Controller
    @RequestMapping("consumer/user")
    @DefaultProperties(defaultFallback = "FallbackMethod")//定义全局熔断方法
    public class UserController {
        @Autowired
        private UserClient userClient;
        @GetMapping
        @ResponseBody
        @HystrixCommand
        public String queryUserById(@RequestParam("id") Integer id) {
            return this.userClient.queryUserById(id).toString();
        }
    
         //定义熔断方法,和被熔断方法的返回值一样
        public String FallbackMethod() {
            return "服务正忙,请稍后再试";
    
        }
      }
    
    1.2.4.设置超时时间
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 6000 # 设置hystrix的超时时间为6000ms
    
    1.2.5.熔断原理

    熔断机制原理很简单,和家里的电路一样,发生短路保险会烧断,来保护电路;

    熔断状态机3个状态:

    • Closed:关闭状态,所有请求都正常访问。
    • Open:打开状态,所有请求都会被降级。Hystix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
    • Half Open:半开状态,open状态不是永久的,打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放部分请求通过,若这些请求都是健康的,则会完全关闭断路器,否则继续保持打开,再次进行休眠计时。

    2.Feign

    跨服务调用,使用方便

    2.1.导入依赖:

    service-consumer:

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    

    2.2.开启Feign功能

    @SpringBootApplication
    @EnableDiscoveryClient //启动客户端
    @EnableFeignClients  //启用Feign组件代替RestTemplate远程调用 :其中包含熔断和负载均衡
    public class ServiceConsumerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(ServiceConsumerApplication.class,args);
        }
    }
    

    2.3.Feign调用的接口

    • 首先这是一个接口,Feign会通过动态代理,帮我们生成实现类。这点跟mybatis的mapper很像
    • @FeignClient,声明这是一个Feign客户端,类似@Mapper注解。同时通过value属性指定服务名称
    • 接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果
    @FeignClient(value = "service-provider") // 标注该类是一个feign接口
    public interface UserClient {
    
        @GetMapping("user/{id}")     //和你需要调用的另一个服务的方法的路径一致
        User queryById(@PathVariable("id") Long id);
    }
    

    2.4.负载均衡

    Feign中本身已经集成了Ribbon依赖和自动配置:

    2.5.Hystrix支持

    Feign默认也有对Hystrix的集成:

    • 开启Feign的熔断功能
    feign:
      hystrix:
        enabled: true # 开启Feign的熔断功能
    
    • 编写一个类,定义熔断方法,实现Feigin调用的接口
    @Component
    public class UserClientFallback implements UserClient {
    
        @Override
        public User queryById(Long id) {
            User user = new User();
            user.setUserName("服务器繁忙,请稍后再试!");
            return user;
        }
    }
    
    • 然后在接口的注解中指定该类为熔断类
    @FeignClient(value = "service-provider", fallback = UserClientFallback.class) // 标注该类是一个feign接口
    public interface UserClient {
    
        @GetMapping("user/{id}")
        User queryUserById(@PathVariable("id") Long id);
    }
    

    3.Zuul网关

    作用:不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都会经过Zuul这个网关,然后再由网关来实现 鉴权、动态路由等等操作。Zuul就是我们服务的统一入口。

    1.快速入门

    1.1.编写配置
    server:
      port: 10010 #服务端口
    spring:
      application:
        name: api-gateway #指定服务名
    
    1.2.编写引导类

    通过@EnableZuulProxy 注解开启Zuul的功能:

    @SpringBootApplication
    @EnableZuulProxy // 开启网关功能
    public class ItcastZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(ItcastZuulApplication.class, args);
    }
    }
    
    1.3.编写路由规则

    Zuul来代理service-provider服务和service-customer服务,

    映射规则:

    server:
      port: 10010 #服务端口
    spring:
      application:
        name: api-gateway #指定服务名
    zuul:
      routes:
      prefix: /api         #前缀
         service-provide: /user/**      #路由的名称,一般为服务名
         service-consumer: /consumer/**
    

    path: http://127.0.0.1:10010/api/user/**

    2.过滤器

    Zuul作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作我们往往是通过Zuul提供的过滤器来实现的。

    2.1.ZuulFilter
    public abstract ZuulFilter implements IZuulFilter{
    
        abstract public String filterType();
    
        abstract public int filterOrder();
        
        boolean shouldFilter();// 来自IZuulFilter
    
        Object run() throws ZuulException;// IZuulFilter
    }
    
    • shouldFilter:返回一个Boolean值,判断该过滤器是否需要执行。返回true执行,返回false不执行。

    • run:过滤器的具体业务逻辑。

    • filterType:返回字符串,代表过滤器的类型。包含以下4种:

      • pre:请求在被路由之前执行
      • route:在路由请求时调用
      • post:在route和errror过滤器之后调用
      • error:处理请求时发生错误调用
    • filterOrder:通过返回的int值来定义过滤器的执行顺序,数字越小优先级越高。

      2.2.自定义过滤器
    @Component
    public class LoginFilter extends ZuulFilter {
        /**
         * 过滤器类型,前置过滤器
         * @return
         */
        @Override
        public String filterType() {
            return "pre";
        }
    
        /**
         * 过滤器的执行顺序
         * @return
         */
        @Override
        public int filterOrder() {
            return 1;
        }
    
        /**
         * 该过滤器是否生效
         * @return
         */
        @Override
        public boolean shouldFilter() {
            return true;
        }
    
        /**
         * 登陆校验逻辑
         * @return
         * @throws ZuulException
         */
        @Override
        public Object run() throws ZuulException {
            // 获取zuul提供的上下文对象
            RequestContext context = RequestContext.getCurrentContext();
            // 从上下文对象中获取请求对象
            HttpServletRequest request = context.getRequest();
            // 获取token信息
            String token = request.getParameter("access-token");
            // 判断
            if (StringUtils.isBlank(token)) {
                // 过滤该请求,不对其进行路由
                context.setSendZuulResponse(false);
                // 设置响应状态码,401
                context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
                // 设置响应信息
                context.setResponseBody("{"status":"401", "text":"request error!"}");
            }
            // 校验通过,把登陆信息放入上下文信息,继续向后执行
            context.set("token", token);
            return null;
        }
    }
    
  • 相关阅读:
    manjaro更换源
    质子重离子快速蒙卡MCsquare在ubuntu-20.04下的安装
    虚拟机硬盘容量不够如何解决
    《收获,不止oracle》读书笔记-未完
    Jenkins 性能:如何避免陷阱、诊断问题和扩展
    这是一个人工智能,你有什么紧急情况?
    人工智能:备忘单
    AI 变得越来越聪明、越来越快。这创造了我们无法回答的棘手问题
    什么是人工智能?你需要知道的关于人工智能的一切
    jenkins构建成功为何显示蓝色
  • 原文地址:https://www.cnblogs.com/cqyp/p/13288374.html
Copyright © 2020-2023  润新知