aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKim Alvefur <zash@zash.se>2023-11-11 23:08:34 +0100
committerKim Alvefur <zash@zash.se>2023-11-11 23:08:34 +0100
commit8e2ecac95b17cabc13a61a3d91ed99f350412f75 (patch)
tree80dffaf23f00b052128c0e24c9a202da0ff01da6
parent1c4021b70feb60c101c39c499dda83729755aa3e (diff)
downloadprosody-8e2ecac95b17cabc13a61a3d91ed99f350412f75.tar.gz
prosody-8e2ecac95b17cabc13a61a3d91ed99f350412f75.zip
net.http: Add simple connection pooling
This should speed up repeated requests to the same site by keeping their connections around and sending more requests on them. Sending multiple requests at the same time is not supported, instead a request started while another to the same authority is in progress would open a new one and the first one to complete would go back in the pool. This could be investigated in the future. Some http servers limit the number of requests per connection and this is not tested and could cause one request to fail, but hopefully it will close the connection and prevent it from being reused.
-rw-r--r--net/http.lua39
1 files changed, 38 insertions, 1 deletions
diff --git a/net/http.lua b/net/http.lua
index 07c7d41f..2685b491 100644
--- a/net/http.lua
+++ b/net/http.lua
@@ -51,10 +51,19 @@ local function log_if_failed(req, ret, ...)
return ...;
end
-local function destroy_request(request)
+local function destroy_request(request, force)
local conn = request.conn;
if conn then
request.conn = nil;
+ local pool = request.http.pool;
+ if pool and not force then
+ local pool_id = request.scheme .. "://" .. request.authority;
+ if not pool[pool_id] then
+ pool[conn] = pool_id;
+ pool[pool_id] = conn;
+ return;
+ end
+ end
conn:close()
end
end
@@ -193,6 +202,13 @@ function listener.ondisconnect(conn, err)
if request and request.conn then
request:reader(nil, err or "closed");
end
+ if request and request.http.pool then
+ local pool = request.http.pool;
+ local pool_id = pool[conn];
+ if pool_id then
+ pool[pool_id], pool[conn] = nil, nil;
+ end
+ end
requests[conn] = nil;
end
@@ -296,6 +312,23 @@ local function request(self, u, ex, callback)
end
end
+ if self.pool then
+ local pool_id = req.scheme .. "://" .. req.authority;
+ local conn = self.pool[pool_id];
+ if conn then
+ log("debug", "Re-using connection to %s from pool", req.host);
+ self.pool[pool_id] = nil;
+ self.pool[conn] = nil;
+ req.conn = conn;
+ requests[conn] = req;
+ self.events.fire_event("request", { http = self, request = req, url = u });
+ listener.onconnect(conn);
+ return req;
+ else
+ log("debug", "Opening a new connection for this request");
+ end
+ end
+
local http_service = basic_resolver.new(host, port_number, "tcp", { servername = req.host; use_dane = use_dane });
connect(http_service, listener, { sslctx = sslctx }, req);
@@ -332,6 +365,10 @@ local function new(options)
end or new;
events = events.new();
};
+ if options and options.connection_pooling then
+ -- util.cache in the future?
+ http.pool = {};
+ end
return http;
end