前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >我们为什么“暂时”干掉了线程池

我们为什么“暂时”干掉了线程池

作者头像
闲宇非鱼
发布2022-02-08 11:20:01
2400
发布2022-02-08 11:20:01
举报

人生苦短,不如养狗

一、背景

  经历了考研“溺水”、亲人离别之后,闲鱼又恬不知耻地回到了原先的公司,重归队伍。此处感谢各位领导和老板,还有帅气的敏哥,以及团队的各位成员。   重回部门,看到那熟悉又陌生的项目代码,不由得感到一阵亲切。还是那个熟悉的味。。。咦?怎么原先所有的线程池都被改成了MQ?难道出bug了?   此时,闲鱼的鬓角不禁流下一滴冷汗。在网上因为线程池使用不当导致的系统崩溃问题屡见不鲜,作为一个菜鸟coder的闲鱼,会犯错也是的正常的,吧?   闲鱼表面波澜不惊、内心慌得一批地打开钉钉,咨询了下目前负责的同事。还好还好,不是出bug了。松了一口气的同时,闲鱼不禁奇怪:既然没有出bug,那么为什么在项目中干掉了线程池呢?

二、何弃疗?改线程池为RocketMQ

  结合前面学习的线程以及线程池的知识,闲鱼仔细思考了一下,有了一些思路。

  • 线程池参数设置没有通用化公式。 虽然在各类博客或者书本中,我们可以看到各种看似标准的线程池参数设置方式,但是实际上对于线程池参数的设置必须有丰富的经验,一旦设置不当,或是maximumPoolSize设置小了,或是阻塞队列长度选取不对,都会导致各种糟糕的后果。下图是截取的美团技术团队关于线程池文章中对于线程池设置的调研结果:
  • 线程池的状态和线程池中任务的状态监控起来比较困难。 在项目中,对于工作线程的监控一般只能通过登录到宿主机上,使用jstack等JDK工具查看堆栈情况。这样的操作费时且费力,而且不能做到实时监测。
  • 最后一个原因应该和目前的产品线所处的背景有关。 目前项目处于快速迭代的过程,需要进行快速停机部署。由于监控困难,线程池中是否正在进行或者等待的任务将无法确定,此时如果服务被下掉,这些正在处理或者等待处理的任务将无法再次启动,所以项目发布必须等待所有任务全部完成或者终止,这就使得我们没有办法做到用户无感知的发布。

相比使用线程池,RocketMQ有以下优势可以解决上述的问题:

  • 相比使用内存来保存任务的线程池,RocketMQ通过使用使用磁盘极大程度上扩大了它存储消息任务的能力。 同时,RocketMQ通过使用CommitLog和ConsumeQueue的存储结构以及mmap等传输方式,使得使用磁盘IO的效率和使用内存的效率相差无几。
  • 阿里云版本的RocketMQ提供了非常完善的监控平台和消息追踪。 通过监控平台和消息轨迹图,我们就能很明确的了解到消息的消费和流转情况。相比线程池的难易监控,这一点是非常优秀的。
  • 消息重发机制。 RocketMQ对于消费失败的消息提供了消息重发机制,除此以外,我们还可以通过控制中心手动进行消息重发。这样,即使因为服务重新部署而消息被消费任务没有执行成功,我们也能手动恢复。

  啧啧,这么分析下来,感觉使用MQ的方式好像确实要优于线程池啊。但是,线程池就真的不能用吗?

三、确定不能再抢救一下了?

  相比线程池这种基于线程的方式,跨进程的MQ在使用成本上毫无疑问是非常高的。虽然有上述的那些缺点,但是真的就没办法使用线程池了吗?   闲鱼又翻了翻美团技术团队的文章,不愧是大团队,还是有思路的(一时白嫖一时爽,一直白嫖一直爽)。其实很简单,就是针对上面的问题进行逐个解决:

  • 参数配置动态化。 其实对于线程池而言,最重要的参数不外乎就是下面三个:corePoolSize、maximumPoolSize以及workQueue。只要将这三个参数的配置放置在配置中心,根据实际业务情况进行动态的配置,那么就能很大程度上避免内存泄漏等问题。
  • 增加线程和线程池的监控。 这部分可能会较为困难,需要单独编写相应的服务进行监控。也有博客中提到使用Arthas,这款Java诊断工具依然需要部署到虚拟机上,虽然会比jstack更加方便直观,但是还是要登录到服务器。

  最后一个问题其实还是比较难以解决的,无论怎么想都需要一个外部存储来存储正在执行的任务或者等待执行的任务,否则一旦重启必定会导致线程池中的任务丢失。   但是仔细考虑一下现在的项目情况,我们有许多的私有化部署需求。如果进行私有化,项目一旦发布到私有云上,基本应该不会进行频繁迭代或者服务重启的情况。放弃了线程池的我们就需要对自建的RocketMQ进行相应的维护,使用成本上可能会有所提高,毕竟和阿里云版本的RocketMQ相比,开源版本还是有所差距的。

四、总结

  是线程池还是MQ,这个问题还是需要根据实际业务场景来进行分析。可能这个阶段需要的是线程池,下一个阶段就需要RocketMQ了。这就需要拥有对于线程池和RocketMQ的底层原理的深刻理解和丰富的使用经验了。那么如何获取这些呢?好好加班啊骚年!   疫情依旧,希望大家能够好好保重身体,好好学习,天天向上,哈哈哈~

参考资料

Java线程池实现原理及其在美团业务中的实践

以及闲鱼的个人博客: https://www.swzgeek.com

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Brucebat的伪技术鱼塘 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、背景
  • 二、何弃疗?改线程池为RocketMQ
  • 三、确定不能再抢救一下了?
  • 四、总结
  • 参考资料
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档