线程池隔离

提供一种新的线程池管理方式,用于隔离服务之间的线程池

特性说明

一种新的线程池管理方式,使得提供者应用内各个服务的线程池隔离开来,互相独立,某个服务的线程池资源耗尽不会影响其他正常服务。支持线程池可配置化,由用户手动指定。

使用场景

使用方式

目前可以以 API、XML、Annotation 的方式进行配置

配置参数

  • ApplicationConfig 新增 String executor-management-mode 参数,配置值为 defaultisolation ,默认为 default
    • executor-management-mode = default 使用原有 以协议端口为粒度、服务间共享 的线程池管理方式
    • executor-management-mode = isolation 使用新增的 以服务三元组为粒度、服务间隔离 的线程池管理方式
  • ServiceConfig 新增 Executor executor 参数,用以服务间隔离的线程池,可以由用户配置化、提供自己想要的线程池,若没有指定,则会根据协议配置(ProtocolConfig)信息构建默认的线程池用以服务隔离。

ServiceConfig 新增 Executor executor 配置参数只有指定executor-management-mode = isolation 才生效。

API

  1. public void test() {
  2. // provider app
  3. DubboBootstrap providerBootstrap = DubboBootstrap.newInstance();
  4. ServiceConfig serviceConfig1 = new ServiceConfig();
  5. serviceConfig1.setInterface(DemoService.class);
  6. serviceConfig1.setRef(new DemoServiceImpl());
  7. serviceConfig1.setVersion(version1);
  8. // set executor1 for serviceConfig1, max threads is 10
  9. NamedThreadFactory threadFactory1 = new NamedThreadFactory("DemoService-executor");
  10. ExecutorService executor1 = Executors.newFixedThreadPool(10, threadFactory1);
  11. serviceConfig1.setExecutor(executor1);
  12. ServiceConfig serviceConfig2 = new ServiceConfig();
  13. serviceConfig2.setInterface(HelloService.class);
  14. serviceConfig2.setRef(new HelloServiceImpl());
  15. serviceConfig2.setVersion(version2);
  16. // set executor2 for serviceConfig2, max threads is 100
  17. NamedThreadFactory threadFactory2 = new NamedThreadFactory("HelloService-executor");
  18. ExecutorService executor2 = Executors.newFixedThreadPool(100, threadFactory2);
  19. serviceConfig2.setExecutor(executor2);
  20. ServiceConfig serviceConfig3 = new ServiceConfig();
  21. serviceConfig3.setInterface(HelloService.class);
  22. serviceConfig3.setRef(new HelloServiceImpl());
  23. serviceConfig3.setVersion(version3);
  24. // Because executor is not set for serviceConfig3, the default executor of serviceConfig3 is built using
  25. // the threadpool parameter of the protocolConfig ( FixedThreadpool , max threads is 200)
  26. serviceConfig3.setExecutor(null);
  27. // It takes effect only if [executor-management-mode=isolation] is configured
  28. ApplicationConfig applicationConfig = new ApplicationConfig("provider-app");
  29. applicationConfig.setExecutorManagementMode("isolation");
  30. providerBootstrap
  31. .application(applicationConfig)
  32. .registry(registryConfig)
  33. // export with tri and dubbo protocol
  34. .protocol(new ProtocolConfig("tri", 20001))
  35. .protocol(new ProtocolConfig("dubbo", 20002))
  36. .service(serviceConfig1)
  37. .service(serviceConfig2)
  38. .service(serviceConfig3);
  39. providerBootstrap.start();
  40. }

XML

  1. <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  2. xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
  3. xmlns="http://www.springframework.org/schema/beans"
  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
  5. http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
  6. <!-- NOTE: we need config executor-management-mode="isolation" -->
  7. <dubbo:application name="demo-provider" executor-management-mode="isolation">
  8. </dubbo:application>
  9. <dubbo:config-center address="zookeeper://127.0.0.1:2181"/>
  10. <dubbo:metadata-report address="zookeeper://127.0.0.1:2181"/>
  11. <dubbo:registry id="registry1" address="zookeeper://127.0.0.1:2181?registry-type=service"/>
  12. <dubbo:protocol name="dubbo" port="-1"/>
  13. <dubbo:protocol name="tri" port="-1"/>
  14. <!-- expose three service with dubbo and tri protocol-->
  15. <bean id="demoServiceV1" class="org.apache.dubbo.config.spring.impl.DemoServiceImpl"/>
  16. <bean id="helloServiceV2" class="org.apache.dubbo.config.spring.impl.HelloServiceImpl"/>
  17. <bean id="helloServiceV3" class="org.apache.dubbo.config.spring.impl.HelloServiceImpl"/>
  18. <!-- customized thread pool -->
  19. <bean id="executor-demo-service"
  20. class="org.apache.dubbo.config.spring.isolation.spring.support.DemoServiceExecutor"/>
  21. <bean id="executor-hello-service"
  22. class="org.apache.dubbo.config.spring.isolation.spring.support.HelloServiceExecutor"/>
  23. <!-- this service use [executor="executor-demo-service"] as isolated thread pool-->
  24. <dubbo:service executor="executor-demo-service"
  25. interface="org.apache.dubbo.config.spring.api.DemoService" version="1.0.0" group="Group1"
  26. timeout="3000" ref="demoServiceV1" registry="registry1" protocol="dubbo,tri"/>
  27. <!-- this service use [executor="executor-hello-service"] as isolated thread pool-->
  28. <dubbo:service executor="executor-hello-service"
  29. interface="org.apache.dubbo.config.spring.api.HelloService" version="2.0.0" group="Group2"
  30. timeout="5000" ref="helloServiceV2" registry="registry1" protocol="dubbo,tri"/>
  31. <!-- not set executor for this service, the default executor built using threadpool parameter of the protocolConfig -->
  32. <dubbo:service interface="org.apache.dubbo.config.spring.api.HelloService" version="3.0.0" group="Group3"
  33. timeout="5000" ref="helloServiceV3" registry="registry1" protocol="dubbo,tri"/>
  34. </beans>

Annotation

  1. @Configuration
  2. @EnableDubbo(scanBasePackages = "org.apache.dubbo.config.spring.isolation.spring.annotation.provider")
  3. public class ProviderConfiguration {
  4. @Bean
  5. public RegistryConfig registryConfig() {
  6. RegistryConfig registryConfig = new RegistryConfig();
  7. registryConfig.setAddress("zookeeper://127.0.0.1:2181");
  8. return registryConfig;
  9. }
  10. // NOTE: we need config executor-management-mode="isolation"
  11. @Bean
  12. public ApplicationConfig applicationConfig() {
  13. ApplicationConfig applicationConfig = new ApplicationConfig("provider-app");
  14. applicationConfig.setExecutorManagementMode("isolation");
  15. return applicationConfig;
  16. }
  17. // expose services with dubbo protocol
  18. @Bean
  19. public ProtocolConfig dubbo() {
  20. ProtocolConfig protocolConfig = new ProtocolConfig("dubbo");
  21. return protocolConfig;
  22. }
  23. // expose services with tri protocol
  24. @Bean
  25. public ProtocolConfig tri() {
  26. ProtocolConfig protocolConfig = new ProtocolConfig("tri");
  27. return protocolConfig;
  28. }
  29. // customized thread pool
  30. @Bean("executor-demo-service")
  31. public Executor demoServiceExecutor() {
  32. return new DemoServiceExecutor();
  33. }
  34. // customized thread pool
  35. @Bean("executor-hello-service")
  36. public Executor helloServiceExecutor() {
  37. return new HelloServiceExecutor();
  38. }
  39. }
  1. // customized thread pool
  2. public class DemoServiceExecutor extends ThreadPoolExecutor {
  3. public DemoServiceExecutor() {
  4. super(10, 10, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(),
  5. new NamedThreadFactory("DemoServiceExecutor"));
  6. }
  7. }
  1. // customized thread pool
  2. public class HelloServiceExecutor extends ThreadPoolExecutor {
  3. public HelloServiceExecutor() {
  4. super(100, 100, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(),
  5. new NamedThreadFactory("HelloServiceExecutor"));
  6. }
  7. }
  1. // "executor-hello-service" is beanName
  2. @DubboService(executor = "executor-demo-service", version = "1.0.0", group = "Group1")
  3. public class DemoServiceImplV1 implements DemoService {
  4. @Override
  5. public String sayName(String name) {
  6. return "server name";
  7. }
  8. @Override
  9. public Box getBox() {
  10. return null;
  11. }
  12. }
  1. // not set executor for this service, the default executor built using threadpool parameter of the protocolConfig
  2. @DubboService(version = "3.0.0", group = "Group3")
  3. public class HelloServiceImplV2 implements HelloService {
  4. private static final Logger logger = LoggerFactory.getLogger(HelloServiceImplV2.class);
  5. @Override
  6. public String sayHello(String name) {
  7. return "server hello";
  8. }
  9. }
  1. @DubboService(executor = "executor-hello-service", version = "2.0.0", group = "Group2")
  2. public class HelloServiceImplV3 implements HelloService {
  3. private static final Logger logger = LoggerFactory.getLogger(HelloServiceImplV3.class);
  4. @Override
  5. public String sayHello(String name) {
  6. return "server hello";
  7. }
  8. }

最后修改 December 16, 2022: Fix check (#1736) (97972c1)