• SpringCloud


    总结

    1. 线程池模式 vs 信号量模式

     线程池隔离信号量隔离
    线程 与调用线程非相同线程 与调用线程相同(tomcat/jetty线程)
    开销 排队、调度、上下文开销等 无线程切换,开销低
    异步 可以是异步,也可以是同步。看调用的方法 同步调用,不支持异步
    并发支持 支持(最大线程池大小hystrix.threadpool.default.maximumSize) 支持(最大信号量上限maxConcurrentRequests)  
    是否超时  支持,可直接返回 不支持,如果阻塞,只能通过调用协议(如:socket超时才能返回)
    是否支持熔断

    支持,当线程池到达maxSize后,并且工作队列也满,再请求会触发fallback接口进行熔断

    支持,当信号量达到maxConcurrentRequests后。再请求会触发fallback
    隔离原理 每个服务单独用线程池 通过信号量的计数器
    资源开销   大,大量线程的上下文切换,容易造成机器负载高 小,只是个计数器 
    使用场景 当请求的服务网络开销比较大的时候,或者是请求比较耗时的时候。为了保证可以大量的容器(tomcat)线程可用,不会由于服务原因,一直处于阻塞或等待状态,会pick this 当请求不耗时,返回通常很快,不会占用容器线程太长的时间;pick this 同时也减少了线程切换的开销。

    下图的左边2/3是线程池资源隔离示意图,右边的1/3是信号量资源隔离示意图,我们先来看左边的示意图。

    我们先来看左边的示意图。

    当用户请求服务A和服务I的时候,tomcat的线程(图中蓝色箭头标注)会将请求的任务交给服务A和服务I的内部线程池里面的线程(图中橘色箭头标注)来执行,tomcat的线程就可以去干别的事情去了,当服务A和服务I自己线程池里面的线程执行完任务之后,就会将调用的结果返回给tomcat的线程,从而实现资源的隔离,当有大量并发的时候,服务内部的线程池的数量就决定了整个服务的并发度,例如服务A的线程池大小为10个,当同时有12请求时,只会允许10个任务在执行,其他的任务被放在线程池队列中,或者是直接走降级服务,此时,如果服务A挂了,就不会造成大量的tomcat线程被服务A拖死,服务I依然能够提供服务。整个系统不会受太大的影响。

    1.1 线程池模式的优缺点

    优点:

    • 一个依赖可以给予一个线程池,这个依赖的异常不会影响其他的依赖。
    • 使用线程池模式可以完全隔离第三方代码,请求线程(客户端的线程)可以快速放回。
    • 当一个失败的依赖再次变成可用时,线程池将清理,并立即恢复可用,而不是一个长时间的恢复。
    • 可以完全模拟异步调用,方便异步编程。
    • 使用线程池,可以有效的进行实时监控、统计和封装。

    缺点:

    • 使用线程池的缺点主要是增加了计算的开销。每一个依赖调用都会涉及到队列,调度,上下文切换,而这些操作都有可能在不同的线程中执行。
    • Netflix 更偏向于使用线程池来隔离依赖服务,因为经过计算,线程切换的消耗在可接受范围之内。并且能支持包括超时在内的所有功能。

    2. 设置隔离模式:线程池/信号量

    execution.isolation.strategy: "THREAD"/"SEMAPHORE"

    @HystrixCommand(
            commandProperties = { //利用commandProperties更改线程池的一些默认配置
                //选择“线程池”模式、"信号量"模式
                @HystrixProperty(name="execution.isolation.strategy",value = "THREAD"/"SEMAPHORE"), 
                //超时
                @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
                //信号量大小为10,那么同时只允许10个tomcat的线程(此处是tomcat的线程,而不是服务的独立线程池里面的线程)来访问服务,其他的请求就会被拒绝,从而达到限流保护的作用
                @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests",value = "10"),
            },
    )
    public List<License> getLicensesByOrg(String organizationId){
        //....
    }

    3. 设置隔离线程池、线程数量、队列长度、fallback方法

    默认情况下,Hystrix不做线程隔离,因此容易造成服务雪崩...

    如果想设置隔离线程池,需要:

    @HystrixCommand(
            //设置一个隔离的线程池
            threadPoolKey = "licenseByOrgThreadPool",
            threadPoolProperties = {
                //设置该线程池的线程数
                @HystrixProperty(name = "coreSize",value="30"),
                //设置队列的容量,该队列的作用是当线程池中的线程都处于工作状态,接下来的请求会进入该队列
                @HystrixProperty(name="maxQueueSize", value="10")
            }
            //一旦队列中也满了,再来的请求就执行“服务降级”fallback方法
            fallbackMethod = "buildFallbackLicenseList"
    )
    public List<License> getLicensesByOrg(String organizationId){
        //...
    }

    参考文献

    服务容错保护断路器Hystrix之八:Hystrix资源隔离策略

  • 相关阅读:
    java继承
    c#中委托和事件区别
    c#委托中的匿名方法和lambda表达式
    c#中内置委托
    iOS消息推送获取不到deviceToken解决方案
    python+appium+iOS自动化测试case如何写?
    Xcode查看iOS崩溃与崩溃日志分析
    iOS性能检测工具instrunments简单介绍
    python实现使用代码进行代理配置
    python+locust性能测试-最简单的登录点击次数
  • 原文地址:https://www.cnblogs.com/frankcui/p/14459929.html
Copyright © 2020-2023  润新知