当前位置: 首页 > news >正文

apache连接池机制讨论

apache连接池的连接有效性

server一般会配置keep-alive超时时间,过了这个时间还没新请求到来,则关闭连接。客户端从连接池里拿出连接时,会检查一下连接是否已关闭,如已关闭,会丢弃掉该连接,并尝试从连接池再拿一个新的连接,代码机制在AbstractConnPool.lease方法里:

public Future<E> lease(final T route, final Object state, final FutureCallback<E> callback) {
        Args.notNull(route, "Route");
        Asserts.check(!this.isShutDown, "Connection pool shut down");
        return new Future<E>() {
            ...
            public E get(long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
                while(true) {
                    synchronized(this) {
                        PoolEntry var10000;
                        try {
                            E entry = (PoolEntry)this.entryRef.get();
                            if (entry != null) {
                                var10000 = entry;
                            } else {
                                ...
                               // 从连接池租借一个连接
                                E leasedEntry = AbstractConnPool.this.getPoolEntryBlocking(route, state, timeout, timeUnit, this);
                                // 如果租借的连接未关闭,就用该连接返回之
                                if (AbstractConnPool.this.validateAfterInactivity <= 0 || leasedEntry.getUpdated() + (long)AbstractConnPool.this.validateAfterInactivity > System.currentTimeMillis() || AbstractConnPool.this.validate(leasedEntry)) {
                                    if (!this.done.compareAndSet(false, true)) {
                                        AbstractConnPool.this.release(leasedEntry, true);
                                        throw new ExecutionException(AbstractConnPool.operationAborted());
                                    }

                                    this.entryRef.set(leasedEntry);
                                    this.done.set(true);
                                    AbstractConnPool.this.onLease(leasedEntry);
                                    if (callback != null) {
                                        callback.completed(leasedEntry);
                                    }

                                    var10000 = leasedEntry;
                                    return var10000;
                                }
							// 租借的连接已关闭,关闭该连接,并回到while循环开始,继续调用getPoolEntryBlocking获得新的连接,若池子里没有连接,创建一个新连接。
                                leasedEntry.close();
                                AbstractConnPool.this.release(leasedEntry, false);
                                continue;
                            }
                        } catch (IOException var8) {
                           ...
                        }

                        return var10000;
                    }
                }
            }
        };
    }

AbstractConnPool.this.validate会调用connection的isStale方法:

//CPool.java
protected boolean validate(CPoolEntry entry) {
        return !((ManagedHttpClientConnection)entry.getConnection()).isStale();
    }

那么一个连接是如何判定不新鲜(stale)的呢?逻辑如下:

//BHttpConnectionBase.java
public boolean isStale() {
        if (!this.isOpen()) {
            return true;
        } else {
            try {
                int bytesRead = this.fillInputBuffer(1);
                return bytesRead < 0;
            } catch (SocketTimeoutException var2) {
                return false;
            } catch (IOException var3) {
                return true;
            }
        }
    }

fillInputBuffer方法会尝试从socket里读取字节,返回值为读取的字节数,若返回-1,说明连接已关闭。

顺带说一下,实测发现,isStale的判定对于server端正常或异常关闭连接的情况,都能检测到

各web服务器的keep-alive策略配置

很显然,一个用于生产的web服务器是要配置keep-alive超时的,毕竟机器的IO连接资源有限,万一大量的长连接被占用,新来的请求将得不到服务。

fastAPI可以在启动时指定keepalive的超时时间,像这样:

app = FastAPI()

@app.get("/test")
async def root():
    return "Hello fastapi"

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8002, timeout_keep_alive=600)

这里我们指定600s,默认keepalive超时是5s,即5s没有请求则关闭连接

tomcat的keep-alive策略配置在server.xml里,除了keepAliveTimeout之外,还有maxKeepAliveRequests选项,意思是服务多少个请求后就关闭连接,例如下面的例子,在服务5个请求后关闭连接:

<Connector port="8080" protocol="HTTP/1.1"

               connectionTimeout="20000"

               maxThreads="1000"

               acceptCount="100"

               redirectPort="8443"

               URIEncoding="UTF-8"

               maxKeepAliveRequests="5"/>

两个参数的含义如下:

keepAliveTimeout:
The number of milliseconds Tomcat will wait for a subsequent request before closing the connection

maxKeepAliveRequests:
Maximum number of Keep-Alive requests to honor per connection

相关文章:

  • C#:类型定义中使用‌问号(?)
  • Git 提示 “LF will be replaced by CRLF“ 的原因及解决方案
  • 【安全】记录钓鱼邮件中木马病毒的分析溯源
  • WPF 附加属性
  • MySQL锁等待超时问题的排查与解决
  • Python 爬虫:一键解锁 3GPP 标准协议下载难题
  • 基于Netlify + Localtunnel 实现本地项目“无服务器”部署上线
  • 资产管理存储技术栈的二十年演进:从大数据存储到AI驱动的智能管理
  • LeetCode 235. 二叉搜索树的最近公共祖先 java题解
  • 练习:猜数字小游戏
  • SRT协议
  • 企业微信token及相关接口关联分析
  • 界面控件Telerik和Kendo UI 2025 Q1亮点——AI集成与数据可视化
  • leetcode543.二叉树的直径
  • 【系统架构设计师】数据库系统 ② ( 分布式数据库 | 分布式数据库 特点 | 分布式数据库 分层模式 | 两阶段提交协议 - 2PC 协议 )
  • 浅谈WebSocket-FLV
  • 【Mysql】SQL 优化全解析
  • Java爬虫如何解析返回的JSON数据?
  • H3C 防火墙上配置端口映射
  • 旅游CMS选型:WordPress、Joomla与Drupal对比
  • 唐山做网站的电话/搜索引擎营销的特点是什么
  • 吴江区城乡建设管理局网站/网站推广优化之八大方法
  • 免费做网站有哪些/游戏加盟
  • 一个网站的建立需要什么/在线数据分析工具
  • 高效网站推广费用/菏泽seo
  • 网站的花费/百度首页登录官网