我在REST API调用某些Web服务期间使用Apache HTTP Client进行连接池。
奇怪的是,尽管我使用HTTP连接池,但我的表现并没有增加。
我使用Apache HTTP Client连接到我的网络服务,代码如下documentation:
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(200);
cm.setDefaultMaxPerRoute(20);
HttpHost host = new HttpHost("abc.com", 80);
cm.setMaxPerRoute(new HttpRoute(host), 50);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
我正在使用Spring的RestTemplate
使用Spring HttpClient
来围绕Apache的HttpComponentsClientHttpRequestFactory
实现。
但即使我没有使用连接池,即。使用Spring的SimpleClientHttpRequestFactory
,我没有任何性能优势。
我的连接仍需要相同的时间才能完成。
我所做的是实现HTTP连接池的正确方法吗?我做错了吗?
如果我方需要进一步的信息,请告诉我。
答案 0 :(得分:2)
请注意HTTP客户端池的工作方式,可能会在短时间内提高性能。检查下面的分析:
来自PoolingHttpClientConnectionManager javadocs
版本4.4中更改了过时连接的处理。以前,代码会在重新使用之前默认检查每个连接。现在,代码仅检查连接,如果自上次使用连接以来经过的时间超过已设置的超时。默认超时设置为2000ms
从池性能角度来看,这意味着只要管理员默认在2秒的时间内将该路由视为“活动”,就会重用与特定路由的连接。 在2秒不活动之后,与该路由的连接将被视为过时并被丢弃,从而在下次请求该路由时引起连接初始惩罚。
换句话说,开箱即用,池可在2秒内提高连接后的连接性能。重型航线是最受益的。
作为一个简单的测试,将池大小设置为较小的值,例如5 max。在linux上发送5个请求并检查与该路由建立的连接数
watch "netstat -ant | grep <your route IP>"
你应该看到5个连接。等待10或20秒并向同一路径发送2个请求,您应该看到这5个连接已关闭,2个新连接已创建。 使用调试日志记录也可以观察到这一点。 Here是一篇很好的文章作为参考。
答案 1 :(得分:0)
我相信您正在正确设置HttpClients.custom()
和池管理器。
我的实现有一点不同之处在于,我使用HttpClientBuilder.create()
而不是RestTemplate
,而是使用相同的方法调用。根据其他Stack Overflow answer,这不应该有所作为。
我之前在Spring应用程序中使用过此配置并且有很好的好处。我想知道是否反应发生得足够快,以至于你没有看到很大的好处?我能想到的另一件事是, namespace Server
{
class Program
{
static void Main(string[] args)
{
var namedPipeServerStream = new NamedPipeServerStream("myPipe",
PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
Task.Run(() => StartListeningAsync(namedPipeServerStream, (msg) => Console.WriteLine(msg)));
Task.Run(() => SendMessageAsync(namedPipeServerStream));
Console.ReadLine();
}
public static async Task SendMessageAsync(NamedPipeServerStream namedPipeServer)
{
using (var stream = new StreamWriter(namedPipeServer))
{
while (true)
{
await Task.Delay(2000);
try
{
var serialized = JsonConvert.SerializeObject($"Server {DateTime.Now}");
byte[] messageBytes = Encoding.UTF8.GetBytes(serialized);
if (!namedPipeServer.IsConnected)
{
namedPipeServer.WaitForConnection();
Console.WriteLine("Client connected");
}
await namedPipeServer.WriteAsync(messageBytes, 0, messageBytes.Length);
await namedPipeServer.FlushAsync();
namedPipeServer.WaitForPipeDrain();
}
catch (Exception exception)
{
Console.WriteLine($"Exception:{exception}");
}
}
}
}
public static async Task StartListeningAsync(NamedPipeServerStream namedPipeServer, Action<string> messageRecieved)
{
while (true)
{
try
{
StringBuilder messageBuilder = new StringBuilder();
string messageChunk = string.Empty;
byte[] messageBuffer = new byte[1024];
do
{
if (!namedPipeServer.IsConnected)
{
namedPipeServer.WaitForConnection();
Console.WriteLine("Client connected");
}
await namedPipeServer.ReadAsync(messageBuffer, 0, messageBuffer.Length);
messageChunk = Encoding.UTF8.GetString(messageBuffer);
messageBuilder.Append(messageChunk);
messageBuffer = new byte[messageBuffer.Length];
} while (!namedPipeServer.IsMessageComplete);
if (messageRecieved != null)
{
messageRecieved(JsonConvert.DeserializeObject<string>(messageBuilder.ToString()));
}
}
catch (Exception exception)
{
Console.WriteLine($"Exception:{exception}");
}
}
}
}
}
可能无法正确配置。
答案 2 :(得分:0)
您的配置似乎是正确的。您可以使用多线程来使用系统资源来获得性能。
HttpGet get = new HttpGet("http://www.codersjargon.com");
PoolingHttpClientConnectionManager connManager
= new PoolingHttpClientConnectionManager();
CloseableHttpClient client = HttpClients.custom().
setConnectionManager(connManager).build();
MultiHttpClientConnThread thread1 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread2 = new MultiHttpClientConnThread(client, get);
MultiHttpClientConnThread thread3 = new MultiHttpClientConnThread(client, get);
thread1.start();
thread2.start();
thread3.start();
thread1.join();
thread2.join();
thread3.join();