Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 由自己的执行人替换默认SimpleAsynctaskeExecutor的drawnbacks和风险是什么_Java_Spring_Multithreading_Spring Boot_Apache Kafka - Fatal编程技术网

Java 由自己的执行人替换默认SimpleAsynctaskeExecutor的drawnbacks和风险是什么

Java 由自己的执行人替换默认SimpleAsynctaskeExecutor的drawnbacks和风险是什么,java,spring,multithreading,spring-boot,apache-kafka,Java,Spring,Multithreading,Spring Boot,Apache Kafka,个人知识:我读到:“…SimpleAsyncTaskExecutor对于玩具项目来说是可以的,但是对于任何比它更大的项目,它都有点风险,因为它不限制并发线程,也不重用线程。所以为了安全起见,我们还将添加一个任务执行器bean…”以及如何添加我们自己的任务执行器的一个非常简单的示例。但我可以找到任何解释后果的指南,以及一些值得应用的案例 个人愿望:我正在努力为我们的微服务日志提供一个企业架构,并将其发布在卡夫卡主题上。“由于不限制并发线程和不重用它而导致的风险”这句话似乎是合理的,主要是针对我基于

个人知识:我读到:“…SimpleAsyncTaskExecutor对于玩具项目来说是可以的,但是对于任何比它更大的项目,它都有点风险,因为它不限制并发线程,也不重用线程。所以为了安全起见,我们还将添加一个任务执行器bean…”以及如何添加我们自己的任务执行器的一个非常简单的示例。但我可以找到任何解释后果的指南,以及一些值得应用的案例

个人愿望:我正在努力为我们的微服务日志提供一个企业架构,并将其发布在卡夫卡主题上。“由于不限制并发线程和不重用它而导致的风险”这句话似乎是合理的,主要是针对我基于日志的案例

我正在本地桌面上成功地运行下面的代码,但是我想知道我是否正确地提供了自定义任务执行器

我的问题:考虑到我已经在使用kafkatempla(即,默认情况下,同步化、单例和线程安全,至少在理解的范围内,用于生成/发送消息),是否会使用下面的配置在使用SimpleAsynctaskeExecutor时,是否真的朝着正确的方向重用线程并避免意外传播线程创建

生产者配置

@EnableAsync
@Configuration
public class KafkaProducerConfig {

    private static final Logger LOGGER = LoggerFactory.getLogger(KafkaProducerConfig.class);

    @Value("${kafka.brokers}")
    private String servers;

    @Bean
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("KafkaMsgExecutor-");
        executor.initialize();
        return executor;
    }

    @Bean
    public Map<String, Object> producerConfigs() {
        Map<String, Object> props = new HashMap<>();
        props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, servers);
        props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonDeserializer.class);
        return props;
    }

}

这是
SimpleAsyncTaskExecutor的默认实现

protected void doExecute(Runnable task) {
    Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
    thread.start();
}
为每个任务创建新线程,Java中的线程创建并不便宜:()

线程对象使用大量内存,在大型应用程序中,分配和取消分配许多线程对象会产生大量内存管理开销

=>使用此任务执行器重复执行任务将对应用程序性能产生负面影响(此外,默认情况下,此执行器不限制并发任务的数量)

这就是为什么建议您使用线程池实现,线程创建开销仍然存在,但由于线程被重用而不是创建,因此大大减少了线程创建开销

配置
ThreadPoolTaskExecutor
时,应根据应用程序负载正确定义两个值得注意的参数:

  • private int maxPoolSize=Integer.MAX_值

    这是池中的最大线程数

  • private int queueCapacity=Integer.MAX_值

    这是排队的最大任务数。当队列已满时,默认值可能会导致OutOfMemory异常

  • 使用默认值(
    Integer.MAX\u value
    )可能会导致服务器资源不足/崩溃


    您可以通过增加最大池大小
    setMaxPoolSize()
    的数量来提高吞吐量,要减少加载增加时的预热,请将core poolsize设置为更高的值
    setCorePoolSize()
    (当加载增加时,将初始化
    maxPoolSize-corePoolSize
    之间不同的任何线程数量)

    我猜你必须使用Spring,而不是像Akka Streams或Lagom这样的反应式框架?是的,Spring是我们微服务的基础框架。这个问题太广泛和模糊;这里不合适。也许它适用于上面的“@Bean public Executor taskExecutor()…”我的方向正确吗?关于maxPoolSize和queueCapacity,非常值得您的评论。但是,你错过了一些额外的配置运行你的眼睛以上?您是否在我的上述陈述中看到任何奇怪的概念或冲突:“我已经在使用kafkatemplate(即,默认情况下,同步、单例和线程安全,至少用于生成/发送消息)”?在我的公司中,目前有5000万客户在使用我们的移动应用程序,该应用程序使用多个微服务,我们每秒发送150个请求,要求记录每个呼叫。执行器池与kafkatemplate无关。您已经使用了kafkatemplate的异步版本(非阻塞)所以性能应该很快,150个RPS很小。看看这个,谢谢你的反馈,每秒150个请求很小。P/Read只是假设另一个你认为高的数字。我不明白你的意思。kafkatemplate完全依赖于executor,不是吗?我知道kafkatemplate异步版本很快,但Manh的评论对我来说很有意义“分配和释放许多线程对象会造成很大的内存管理开销……默认情况下,该executor不会限制并发任务的数量”。您似乎看到我走错了方向。您能更清楚一点吗?根据“生产者的实现是异步的。消息存储在内部队列中,等待通过内部线程发送,这将通过潜在的批处理提高效率”.这样的内线程不是executor提供的吗?如果是的话,拥有一个池我相信在一些负面场景中会有帮助(例如,MicroDevice容器和Kafka容器之间的连接降低,消息意外激增等等。我说的“这样的内线程正是executor poool提供的”对吗?
    @SpringBootApplication
    public class KafkaDemoApplication  implements CommandLineRunner {
    
        public static void main(String[] args) {
            SpringApplication.run(KafkaDemoApplication.class, args);
    
        }
    
        @Autowired
        private Producer p;
    
        @Override
        public void run(String... strings) throws Exception {
            p.send("test", " qualquer messagem demonstrativa");
        }
    
    }
    
    protected void doExecute(Runnable task) {
        Thread thread = (this.threadFactory != null ? this.threadFactory.newThread(task) : createThread(task));
        thread.start();
    }