apache连接池机制讨论

apache连接池的连接有效性

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

java 复制代码
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方法:

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

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

java 复制代码
//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的超时时间,像这样:

python 复制代码
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个请求后关闭连接:

xml 复制代码
<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
相关推荐
小许学java9 分钟前
Spring AI快速入门以及项目的创建
java·开发语言·人工智能·后端·spring·ai编程·spring ai
AGG_Chan21 分钟前
flutter专栏--深入了解widget原理
开发语言·javascript·flutter
Darenm1111 小时前
JavaScript事件流:冒泡与捕获的深度解析
开发语言·前端·javascript
whltaoin1 小时前
Java 后端与 AI 融合:技术路径、实战案例与未来趋势
java·开发语言·人工智能·编程思想·ai生态
wjs20241 小时前
jEasyUI 自定义窗口工具栏
开发语言
二十雨辰1 小时前
vite与ts的结合
开发语言·前端·vue.js
xiaohanbao091 小时前
Transformer架构与NLP词表示演进
python·深度学习·神经网络
亦良Cool2 小时前
如何部署一个Java项目
java·开发语言
沐知全栈开发2 小时前
JavaScript 输出
开发语言
love530love2 小时前
【笔记】 Podman Desktop 中部署 Stable Diffusion WebUI (GPU 支持)
人工智能·windows·笔记·python·容器·stable diffusion·podman