`

配置TOMCAT及httpClient的keepalive以高效利用长连接

 
阅读更多
总所周知http1.1(http1.0不是标准,依服务器而定)是支持长连接的,长连接能够保证服务器和客户端的socket能够高效利用,减少握手等额外的开销。httpClient在正常情况下会带上Connection: keep-alive表示我是支持长连接的,当完成一个请求后,视情况决定是否关闭连接。



但是如果服务器端连接次数计数达到指定值时,则会在返回内容中添加Connection: close信息,表示该连接将被关闭。



这个时候该connection就失效了,客户端如果下次请求服务器的话,需要重新创建一个新的连接。但是有个问题,是否连接保持是由服务器端决定的,一旦连接超时导致connection close,服务器是不会专门通知客户端的,所以我们不能依赖Connection: close信息来决定是否关闭socket。我们先来看看tomcat对长连接的配置。下面是一个典型的配置长连接的方式:



其中:
keepAliveTimeout:表示在下次请求过来之前,tomcat保持该连接多久。这就是说假如客户端不断有请求过来,且为超过过期时间,则该连接将一直保持。
maxKeepAliveRequests:表示该连接最大支持的请求数。超过该请求数的连接也将被关闭(此时就会返回一个Connection: close头给客户端)。

  由于keeplive的不确定性,这对客户端高效的实现http请求带来了一定挑战。在httpClient中对连接的复用采用了多种机制同时保证,但是这需要和服务器端一起配合。如果服务器端和客户端在keepAlive相关的配置不匹配的话,轻则效率低下,重则伤筋动骨,具体有哪些需要注意的地方?下面一一道来。

http连接池

httpClient提供了连接池实现连接的复用,这是实现高效请求的基础,下面是给httpClient设置连接池的方法:
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
//连接池最大生成连接数200
cm.setMaxTotal(200);
// 默认设置route最大连接数为20
cm.setDefaultMaxPerRoute(20);
// 指定专门的route,设置最大连接数为80
HttpHost localhost = new HttpHost("locahost", 80);
cm.setMaxPerRoute(new HttpRoute(localhost), 50);
// 创建httpClient
CloseableHttpClient httpClient = HttpClients.custom()
        .setConnectionManager(cm)
        .build();


有几个需要注意的地方:
1.如果你的客户端连接的目标服务器只有一个,那么大可设置最大route连接数和最大连接池连接数相同,以便高效利用连接池中创建的连接。
2.创建的httpClient对象是线程安全的,如果连接的目标服务器只有一个的话,创建一个全局对象即可。一个对象好比开了一个浏览器,多个线程无需每次请求时专门开一个浏览器,统一一个即可。
3.如果httpClient对象不再使用,记得关闭,释放与服务器保持连接的socket,以便服务器更高效的释放资源。

连接清理线程

虽然连接池有了,但是由于http连接的特殊性(只有在通讯正在进行(block)时才能够对IO事件做出反应)。一旦连接被放回连接池后,我们无从知道该连接是否还是keepalive的,且此时也无法监控当前socket的状态(即服务器主动关闭了连接,但客户端没有通讯时是不知道当前连接的状态是怎样的)。怎么办呢?httpClient采用了一个折中的方案来检查连接的“状态”,就是由客户端自己通过配置去主动关闭其认为是失效的连接。具体方法如下:

public static class IdleConnectionMonitorThread extends Thread {
   
    private final HttpClientConnectionManager connMgr;
    private volatile boolean shutdown;
   
    public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
        super();
        this.connMgr = connMgr;
    }
    @Override
    public void run() {
        try {
            while (!shutdown) {
                synchronized (this) {
                    wait(5000);
                    // Close expired connections
                    connMgr.closeExpiredConnections();
                    // Optionally, close connections
                    // that have been idle longer than 30 sec
                    connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
                }
            }
        } catch (InterruptedException ex) {
            // terminate
        }
    }
   
    public void shutdown() {
        shutdown = true;
        synchronized (this) {
            notifyAll();
        }
    }
   
}


我们新建了一个Thread,该Thread每隔5s进行一次清理,把认为是expired或空闲超过30s的连接给关闭掉。这里关闭空闲的连接好理解。问题是关闭expired的连接,什么样的连接才算是expired呢?刚才说过客户端是无法检测到对应的连接是否是alive的,故通过一个配置告诉httpClient每个连接大概什么时候会断掉,httpClient会认为过了该时间的连接就是expired的连接。默认情况下,httpClient认为只要连接上服务器的socket将永远不会断掉。显然这种假设过于乐观。

keepalive策略

为了使connMgr.closeExpiredConnections();起到作用,我们需要指定连接keep alive策略,来告诉httpClient,哪些连接大概什么时候会过期,你可以关闭他们。下面是一个设置keep alive 策略的例子

ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
    public long getKeepAliveDuration(HttpResponse response, HttpContext context) {
        // Honor 'keep-alive' header
        HeaderElementIterator it = new BasicHeaderElementIterator(
                response.headerIterator(HTTP.CONN_KEEP_ALIVE));
        while (it.hasNext()) {
            HeaderElement he = it.nextElement();
            String param = he.getName();
            String value = he.getValue();
            if (value != null && param.equalsIgnoreCase("timeout")) {
                try {
                    return Long.parseLong(value) * 1000;
                } catch(NumberFormatException ignore) {
                }
            }
        }
        HttpHost target = (HttpHost) context.getAttribute(
                HttpClientContext.HTTP_TARGET_HOST);
        if ("www.naughty-server.com".equalsIgnoreCase(target.getHostName())) {
            // Keep alive for 5 seconds only
            return 5 * 1000;
        } else {
            // otherwise keep alive for 30 seconds
            return 30 * 1000;
        }
    }
};
CloseableHttpClient client = HttpClients.custom()
        .setKeepAliveStrategy(myStrategy)
        .build();


这个例子指明在访问www.naughty-server.com和其他未知服务器时的keeplive为一个固定值,如果服务器返回keeplive过期时间,则通过服务器告诉客户端该连接大概什么时候过期(注意这不是一个标准的http协议,不是所有服务器都支持)。

总结

如果httpClient是访问单一的地址(如rpc请求),通过与服务器配置配合能够更高效的利用客户端的连接池,例如以tomcat为例,设置maxKeepAliveRequests为-1则可以使该连接可以请求无限次数,而设置keepAliveTimeout为一个较大的时间则可以让客户端更有效的利用连接池中的连接。凡事都有前提,如果目标tomcat即用于rpc调用,又用于服务正常连接请求的话,则上面优化反而会大量消耗服务器资源。这时可以讲这两类服务拆分成两个tomcat进行分别处理。另外,如果在服务器前面配有代理的话(apache,nginx),则还需视情况设置代理的keepAlive策略以提高利用率。

参考:http://backend.blog.163.com/blog/static/2022941262014029105618173/

   http://www.programcreek.com/java-api-examples/index.php?api=org.apache.http.conn.ConnectionKeepAliveStrategy
分享到:
评论
2 楼 sichunli_030 2017-05-23  
对于频繁调用的话,建议采用连接池机制
1 楼 11想念99不见 2017-05-17  
你好,我看不太懂。假如我的项目中会频繁调用rest接口,是要用连接池还是用长连接。

相关推荐

    springboot-keepalive设置测试

    在这个“springboot-keepalive设置测试”项目中,我们将关注的是如何在Spring Boot应用中配置和测试HTTP长连接(keepalive)功能,以优化服务器与客户端之间的通信效率。 HTTP长连接,也被称为持久连接,允许TCP...

    《学生选课系统》概要设计说明书.doc

    《学生选课系统》概要设计说明书.doc

    80万吨 年对二甲苯px项目 初步设计说明书.docx

    80万吨 年对二甲苯px项目 初步设计说明书.docx

    花朵授粉算法改进版NMFPA的技术实现与性能评估

    内容概要:本文介绍了改进版花朵授粉算法(NMFPA)的关键技术和性能提升。主要改进点包括:动态p值调整、惯性权值引入、精英信息共享以及双重扰动策略。通过23个基准测试函数验证,NMFPA在收敛速度、跳出局部最优等方面表现出色。文章详细解析了各个改进模块的工作原理,并提供了完整的Python代码实现,涵盖初始化、授粉过程、扰动策略等核心部分。此外,作者还分享了调参经验和学习建议,强调了动态参数调整和种群多样性的关键作用。 适用人群:对群体智能算法感兴趣的科研人员、算法工程师及研究生。 使用场景及目标:适用于解决连续优化问题,特别是在高维、多峰函数优化场景中。目标是提供一种高效稳定的优化工具,帮助研究者快速掌握并应用改进型花朵授粉算法。 其他说明:文中附带大量代码片段和测试数据,便于读者理解和复现实验结果。建议初学者先熟悉基本的花朵授粉算法,再逐步深入理解各项改进措施。

    比亚迪f3变速器设计说明书.docx

    比亚迪f3变速器设计说明书.docx

    餐馆点菜系统概要设计说明书.doc

    餐馆点菜系统概要设计说明书.doc

    基于webmagic + springboot + mybatis的Java爬虫,使用Echarts进行数据可视化.zip

    基于webmagic + springboot + mybatis的Java爬虫,使用Echarts进行数据可视化.zip

    预算管理在企业管理中作用.docx

    预算管理在企业管理中作用.docx

    【人工智能导论】支持向量机算法分析预习报告:深入理解SVM原理与鸢尾花数据集分类实验设计

    内容概要:本文档为2024~2025学年第二学期的人工智能导论课程中的支持向量机(SVM)算法分析实验预习报告。报告的主要目的是深入理解SVM的基本原理、核函数的作用以及参数调节对模型的影响,同时掌握特征选取的方法和重要性,为后续处理更复杂的数据集积累经验。实验任务包括对鸢尾花数据集进行特征探索,通过绘制相关性矩阵、径向可视化或各特征之间的关系矩阵图,深入了解数据集特征,并利用SVM算法实现对该数据集的准确分类。实验设备和环境要求操作系统为Windows、Linux或macOS均可,编程语言为Python,并搭配NumPy、Pandas、Scikit-learn和Matplotlib等科学计算和数据处理库。; 适合人群:具有一定的数学基础和编程经验,正在学习或从事机器学习和数据挖掘领域工作的学生或研究人员。; 使用场景及目标:①适用于需要理解SVM算法原理及其应用的学习者;②帮助研究者掌握如何使用SVM进行分类任务,特别是针对线性不可分的数据集;③为后续更复杂的机器学习项目提供理论和技术支持。; 其他说明:实验将在图书馆附楼计算中心进行,时间为2025年4月15日,由教师王艳指导并批阅。实验预习过程应详细记录设计思想、设计步骤等初步方案,可以通过程序流程图、伪代码、预定相关测试数据和预期结果等方式来表示。

    裂缝检测数据集,支持yolo v7格式的标注,1673张原始训练集图片,正确识别率99.4%

    裂缝检测数据集,支持yolo v7格式的标注,1673张原始训练集图片,正确识别率99.4% 图片详情可查看博文:https://backend.blog.csdn.net/article/details/147232357

    HPPO法生产环氧丙烷的工艺初步设计说明书项目可行性报告中文摘要.pdf

    HPPO法生产环氧丙烷的工艺初步设计说明书项目可行性报告中文摘要.pdf

    (最新修订版)基于PLC的电线电缆张力测控设计毕业论文设计说明书.doc

    (最新修订版)基于PLC的电线电缆张力测控设计毕业论文设计说明书.doc

    jzs125 360°齿轮齿条摆动液压缸毕业设计说明书.docx

    jzs125 360°齿轮齿条摆动液压缸毕业设计说明书.docx

    三菱PLC与触摸屏在花式喷水池控制系统的应用详解

    内容概要:本文详细介绍了使用三菱FX5U系列PLC和GT2715触摸屏构建花式喷水池控制系统的方法。首先阐述了硬件搭建,包括IO设备的选择与连接方式,如电磁阀、变频器、传感器等,并强调了电气隔离和防护措施的重要性。接着深入解析了梯形图编程逻辑,展示了如何通过不同的模式切换来实现多样化的喷水效果,以及如何利用比较指令、移位指令等实现精确控制。同时探讨了触摸屏组态的设计思路,如模式选择、水压监测、急停保护等功能的实现方法,并提供了VB脚本示例用于增强人机交互体验。此外,还讨论了安全联锁机制、抗干扰措施、通信扩展等方面的内容,分享了许多基于实践经验的技术细节和注意事项。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程及触摸屏应用感兴趣的读者。 使用场景及目标:帮助读者掌握三菱PLC与触摸屏联合使用的技能,能够独立完成类似项目的规划、实施与维护工作,提高对复杂工控系统的理解和应对能力。 其他说明:文中涉及大量实际案例和技术诀窍,对于初学者来说具有一定挑战性,建议结合官方手册进行学习。

    带搅拌装置的夹套传热式反应釜的机械设计说明书.doc

    带搅拌装置的夹套传热式反应釜的机械设计说明书.doc

    树莓派PICO keil包

    树莓派PICO keil包

    发动机机油泵总成性能试验台设计 毕业设计说明书.docx

    发动机机油泵总成性能试验台设计 毕业设计说明书.docx

    滚筒输送机设计说明书.pdf

    滚筒输送机设计说明书.pdf

    《工程设计训练》课程设计说明书 日产7500吨熟料预分解窑的分解炉设计.doc.doc

    《工程设计训练》课程设计说明书 日产7500吨熟料预分解窑的分解炉设计.doc.doc

    基于MATLAB的楼宇负荷需求响应研究:模型预测控制与完全复现

    内容概要:本文详细介绍了如何使用MATLAB和CVX工具箱,通过模型预测控制(MPC)优化楼宇空调系统的能耗管理。首先,作者通过对建筑热力学特性的建模,建立了状态空间模型来描述楼宇的温度变化规律。接着,设计了一个24小时预测时域的MPC控制器,结合动态电价信号,实现了在电价低谷期预冷建筑并在电价高峰期减少制冷功率的目标。文中展示了具体的MATLAB代码片段,解释了关键参数的选择及其物理意义,并讨论了如何通过引入舒适度约束和反馈校正机制提高控制精度。最终,仿真实验表明该方法不仅能够显著降低电费支出,还能保持室内温度在舒适的范围内。 适合人群:从事楼宇自动化、能源管理和控制系统设计的研究人员和技术人员。 使用场景及目标:适用于商业建筑和工业园区的空调系统节能改造项目,旨在通过智能化控制手段实现节能减排和成本优化。 其他说明:文章强调了模型简化与计算效率之间的权衡,以及在实际应用中需要根据不同建筑物的具体情况进行参数调整。同时指出,良好的用户体验是衡量控制算法成功与否的重要标准之一。

Global site tag (gtag.js) - Google Analytics