zoukankan      html  css  js  c++  java
  • 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;
        }
    }
    
  • 相关阅读:
    WCF 第八章 安全 确定替代身份(中)使用AzMan认证
    WCF 第八章 安全 总结
    WCF 第八章 安全 因特网上的安全服务(下) 其他认证模式
    WCF Membership Provider
    WCF 第八章 安全 确定替代身份(下)模仿用户
    WCF 第八章 安全 因特网上的安全服务(上)
    WCF 第九章 诊断
    HTTPS的七个误解(转载)
    WCF 第八章 安全 日志和审计
    基于比较的排序算法集
  • 原文地址:https://www.cnblogs.com/cqyp/p/13288374.html
Copyright © 2011-2022 走看看