业务代码到底需不需要用多线程???

1.dubbo场景下的多线程

先来讲讲dubbo场景,整个调用链路非常的清晰:

图片

来,请你告诉我这里面有线程池吗?

没有!

是的,在日常的开发中,我就是写个接口给别人调用嘛,在我的接口里面并没有线程池相关的代码,只有 CRUD 相关的业务代码。

同时,在日常的开发中,我也经常调用别人提供给我的接口,也是一把梭,撸到底,根本就不会用到线程池。

所以,站在我,一个开发人员的角度,这个里面没有线程池。

但是,当我们换个角度,再看看,它也是可以有的

比如这样:

图片

反应过来没有?

我们发起一个 HTTP 调用,是由一个 web 容器来处理这个请求的,你甭管它是 Tomcat,还是 Jetty、Netty、Undertow 这些玩意,反正是个 web 容器在处理。

那你说,这个里面有线程池吗?

是有的!!

比如说Tomcat,虽然不是你写的,但是你确实用了。

会由 web 容器中的一个线程来进行调用。所以,站在 web 容器的角度,这里是有一个线程池的:

同理,在 RPC 框架中,不管是消费方,还是服务提供方,也都存在着线程池

本篇文章侧重不在dubbo,我就不多说dubbo的线程池了。

我们主要关注这个业务线程池。

反正站在 Dubbo 框架的角度,又可以补充一下这个图片了:

图片

那么问题来了,在当前的这个情况下?

当有人反馈:哎呀,这个服务吞吐量怎么上不去啊?

你怎么办?你会 duang 的一下在业务逻辑里面加一个线程池吗?

图片

大哥,前面有个 web 容器的线程池,后面有个框架的线程池,两头不调整,你在中间加个线程池,加它有啥用啊?对吧。

可以对web容器进行调优,然后对dubbo框架也可以进行调优

甚至,你在业务代码中加入一个线程池之后,反而会被“反噬”。

比如,你 duang 的一下怼个线程池在这里,我们先只看 web 容器和业务代码对应的部分:

图片

由于你的业务代码中有线程池的存在,所以当接受到一个 web 请求之后,立马就把请求转发到了业务线程池中,由线程池中的线程来处理本次请求,从而释放了 web 请求对应的线程,该线程又可以里面去处理其他请求。

这样来看,你的吞吐量确实上去了。

在前端来看,非常的 nice,请求立马得到了响应。

但是,你考虑过下游吗?

你的吞吐量上涨了,下游同一时间处理的请求就变多了。如果下游跟不上处理,顶不住了,直接就是崩给你看怎么办?

图片

而且下游不只是你一个调用方,由于你调用的太猛,导致其他调用方的请求响应不过来,是会引起连锁反应的。

所以,这种场景下,为了异步怼个线程池放着,我觉得还不如用消息队列来实现异步化,顶天了也就是消息堆积嘛,总比服务崩了好,这样更加稳妥。

或者至少和下游勾兑一下,问问我们这边吞吐量上升,你们扛得住不。

图片

我们最开始的案例是想要在业务逻辑中增加一个线程池,对着一个下游服务就是一顿猛攻,不是所谓的串行改并行,而是用更多的线程,带来更多的串行

2.适合用线程池的场景

2.1多个模块收集信息场景

比如一个请求要经过若干个服务获取数据,且这些数据没有先后依赖,最终需要把这些数据组合起来,一并返回,这样经典的场景:

图片

用户点商品详情,你要等半天才展示给用户,那用户肯定骂骂咧咧的久走了。

这个时候,八股文上是怎么说的:用线程池来把串行的动作改成并行

图片

这个场景也是增加了服务 A 的吞吐量,但是用线程池就是非常正确的,没有任何毛病。

2.2定时任务触发调用场景

比如你有一个定时任务,要从数据库中捞出状态为初始化的数据,然后去调用另外一个服务的接口查询数据的最终状态。

图片

如果你的业务代码是这样的:

//获取订单状态为初始化的数据(0:初始化 1:处理中 2:成功 3:失败)
//select * from order where order_status=0;
ArrayList initOrderInfoList = queryInitOrderInfoList();
//循环处理这批数据
for(OrderInfo orderInfo : initOrderInfoList){
    //捕获异常以免一条数据错误导致循环结束
    try{
        //发起rpc调用
        String orderStatus = queryOrderStatus(orderInfo.getOrderId);
        //更新订单状态
        updateOrderInfo(orderInfo.getOrderId,orderStatus);  
    } catch (Exception e){
        //打印异常
    }
}

虽然你框架中使用了线程池,但是你就是在一个 for 循环中不停的去调用下游服务查询数据状态,是一条数据一条数据的进行处理,所以其实同一时间,只是使用了框架的线程池中的一个线程。

为了更加快速的处理完这批数据,这个时候,你就可以怼一个线程池放在 for 循环里面了:

//循环处理这批数据
for(OrderInfo orderInfo : initOrderInfoList){
    //使用线程池
    executor.execute(() -> {
        //捕获异常以免一条数据错误导致循环结束
        try {
            //发起rpc调用
            String orderStatus = queryOrderStatus(orderInfo.getOrderId);
            //更新订单状态
            updateOrderInfo(orderInfo.getOrderId, orderStatus);
        } catch (Exception e) {
            //打印异常
        }
    });
}

图片

需要注意的是,这个线程池的参数怎么去合理的设置,是需要考虑的事情。

同时这个线程池的定位,就类似于 web 容器线程池的定位。

或者这样对比起来看更加清晰一点:

图片

定时任务触发的时候,在发起远程接口调用之前,没有线程池,所以我们可以启用一个线程池来加快数据的处理。

而 Http 调用或者 RPC 调用,框架中本来就已经有一个线程池了,而且也给你提供了对应的性能调优参数配置,那么首先考虑的应该是把这个线程池充分利用起来。

如果仅仅是因为异步化之后可以提升服务响应速度,没有达到串行改并行的效果,那么我更加建议使用消息队列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/153349.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RedCap推动5G规模应用,紫光展锐赋能产业高质量发展

5G R17 RedCap作为面向中高速物联网场景的关键技术和解决方案,可以大幅降低终端的复杂度、成本和功耗。在当前国内5G应用规模化发展关键时期,5G R17 RedCap拥有广大的市场潜力与广泛的应用场景,将有助于推动5G规模应用、构建融通发展的5G生态…

深眸科技革新升级OCR技术,与AI视觉实现有效融合赋能各行业应用

OCR即光学字符识别,是通过扫描仪或工业相机等电子设备检查打印的字符,并通过检测暗、亮的模式确定其形状,然后用字符识别方法将形状翻译成计算机文字的过程。 目前,随着机器视觉和人工智能技术的进一步升级,OCR技术实…

【Java实现图书管理系统】

图书管理系统 1. 设计背景2. 设计思路3. 模块展示代码演示3.1 Book类3.2 BookList类(书架类)3.4 用户类 - User类3.5 子类管理员类 -- AdminUser类3.6 子类普通用户类 -- NormalUser类3.7 操作接口3.8 操作类3.8.1 查找操作 -- FindOperation类3.8.2 增加…

浅谈青岛啤酒厂事件—论智能视频监控的重要性和必要性

近日,“青岛啤酒三厂有工人在原料仓小便”的视频曝光,引发舆论关注。虽然此次事件原委已经明了,但此次事件也给我们敲了一个警钟。啤酒厂生产的是入口的食品原料,就因一个工作口角就导致有人罔顾大众食品安全,作出严重…

2022年09月 Scratch(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

一、单选题(共25题,每题2分,共50分) 第1题 点击绿旗,下面哪个选项可以实际播放放马叫声并在声音全部播放完后,马向右移动? A: B: C: D: 答案:D

Linux使用Docker完整安装Superset3,同时解决please use superset_config.py to override it报错

文章目录 Docker安装Superset流程1. 首先获取镜像2. 生成SSL3. 创建Superset容器4. 更新数据库5. 测试访问Superset Docker安装Superset流程 1. 首先获取镜像 docker pull amancevice/superset2. 生成SSL 接下来我们运行一些额外的程序: openssl rand -base64 4…

详解如何使用Jenkins一键打包部署SpringBoot项目

目录 1、Jenkins简介 2、Jenkins的安装及配置 2.1、Docker环境下的安装​编辑 2.2、Jenkins的配置 3、打包部署SpringBoot应用 3.1、在Jenkins中创建执行任务 3.2、测试结果 1、Jenkins简介 任何简单操作的背后,都有一套相当复杂的机制。本文将以SpringBoot应…

Kubernetes(k8s)进阶

文章目录 Kubernetes进阶一、Namespace(名称空间)1.namespace介绍2.管理namespace查看namespace创建namespaceyaml文件配置namespace 二、Pod(最小基本部署单元)1.pod介绍2.管理pod创建并运行pod查看pod信息访问pod删除podyaml文件…

信号特点,异步/同步概念,查看信号(kill -l,man 7 signa),实时/分时os概念

目录 引入 共同特点 信号 介绍 特点 异步 概念 同步 查看信号 kill -l 实时操作系统 和 分时操作系统 分时 实时 man 7 signal 引入 生活中有关信号的东西有很多 例如:红绿灯,闹钟,转向灯等等 共同特点 他们都有共同的特点: 我们是认识这些信号的,以及出现这些信…

conda虚拟环境中安装的cuda和服务器上安装的cuda的异同

服务器上已安装Nvidia提供的cuda,nvcc -V时会出现已安装的CUDA版本。如下图所示,服务器上已安装好的cuda版本为10.1。 但是当我们在Anaconda虚拟环境下安装pytorch或者paddlepaddle等深度学习框架的GPU版本时,通常会选择较高版本的cuda&…

Databend 源码阅读: Storage 概况和 Read Partitions

作者:zhyass | Databend Labs 成员,数据库研发工程师 ❤️ 友情提示:代码演进较快,请注意文档的时效性哦! 引言 Databend 将存储引擎抽象成一个名为 Table 的接口,源码位于 query/catalog/src/table.rs。…

java springboot在当前测试类中添加临时属性 不影响application和其他范围

目前 我们的属性基本都写在 application.yml 里面了 但是 如果 我们只是想做一下临时变量的测试 有没有办法实现呢? 显然是有的 这里 我们还是先在application.yml中去写一个 test属性 下面加个prop 然后 我们尝试在测试类中 获取一下这个属性 直接用 Value 读取…

华为Matebook X Pro 2022款 i7 集显(MRG-W76)原装出厂Windows11预装系统21H2

下载链接:https://pan.baidu.com/s/12ru9lUeQ7mWd5u1KLCM0Pg?pwdc7pi 提取码:c7pi 原厂系统自带指纹、面部识别、声卡、网卡、显卡等所有驱动、出厂主题壁纸、Office办公软件、华为电脑管家等预装程序,如图 由于时间关系,绝大部分资料没…

2023-11-16 android 编译提示module freg.default missing dependencies:

一、错误如下: 二、原因 2.1 Andriod.bp 编译的so模块可以被 Android.bp 和 Android.mk 编译依赖。 2.2 Android.mk 编译的so模块仅可以被Android.mk编译的模块依赖,无法被Android.bp编译的模块依赖。 三、参考文章 【Android编译报错:miss…

终于解决!!!the pgadmin4 server could not be contacted

今天尝试用geoserver发布arcgis的gdb数据,说是要用到postgis,于是就安装了,结果刚安装好就遇到这个问题了,pgadmin报错打不开,裤子都没脱就告诉我有错误了,这tm不是欺负老实人吗,于是就开始百度…

第08章 面向对象编程(高级)

一 关键字:static class Circle{private double radius;public Circle(double radius){this.radiusradius;}public double findArea(){return Math.PI*radius*radius;} }创建两个Circle对象: Circle c1new Circle(2.0); //c1.radius2.0 Circle c2new C…

美团面试题

文章目录 1.线程池有几种实现方式?2.线程池的参数含义?3.锁升级的过程?4.i++ 如何保证线程安全?5.HashMap和ConcurrentHashMap有什么区别?6.@Autowired和@Resource区别?7.说说常用的设计模式8.Redis为什么这么快?9.索引的种类?如何优化?1.线程池有几种实现方式? 线程…

爱上C语言:操作符详解(下)

🚀 作者:阿辉不一般 🚀 你说呢:生活本来沉闷,但跑起来就有风 🚀 专栏:爱上C语言 🚀作图工具:draw.io(免费开源的作图网站) 如果觉得文章对你有帮助的话,还请…

《C++ Primer》第9章 顺序容器(二)

参考资料: 《C Primer》第5版《C Primer 习题集》第5版 9.3 顺序容器操作(P305) 9.3.1 向容器中添加元素(P305) 使用push_back 除 array 和 forward_list 外,每个顺序容器都支持 push_back &#xff1a…

在windows下vs c++运行g2o的BA优化程序示例

目录 1、前言2、准备工作安装git安装vcpkg(1)下载(2)安装(3)集成至vs 安装cmake 3、安装g2o4、安装opencv(1)下载(2)双击安装(3)环境变…