我希望优化一个持续运行并通过简单的 REST 风格 HTTP post 频繁调用(平均每秒 > 1 次)外部 API 的流程。我注意到的一件事是,目前,为每个 API 调用创建并关闭 HttpUrlConnection,按照以下结构(为了可读性删除了非必要代码和错误处理)。

//every API call
try {
  URL url = new URL("..remote_site..");
  conn = (HttpURLConnection) url.openConnection();
  setupConnectionOptions(conn); //sets things like timeoout and usecaches false
  outputWriter = new OutputStreamWriter(new BufferedOutputStream(conn.getOutputStream()));
  //send request
} finally {
  conn.disconnect();
  outputWriter.close();
}

我没有直接处理http协议的丰富经验,但是根据常识/套接字知识,似乎只创建一次连接并重新使用它,并且只重新初始化它会更有效在出现问题时,为了避免每次都进行连接协商,如下所示:

//on startup, or error
private void initializeConnection()
{
  URL url = new URL("..remote_site..");
  conn = (HttpURLConnection) url.openConnection();
  setupConnectionOptions(conn); //sets things like timeoout and usecaches false
}

//per request
try {
  outputWriter = new OutputStreamWriter(new BufferedOutputStream(conn.getOutputStream()));
  //send request
} catch (IOException) {
  try conn.disconnect();
  initializeConnection();
} finally {
  outputWriter.close();
}

//on graceful exit
conn.disconnect();

我的问题是:

  • 一般来说,这是一个合理的优化吗(速度提升会很明显)吗?

假设是:

  • 我应该重用输出流以及连接吗?
  • 仅在出现错误时重新初始化连接是否合理,还是应该在一定数量的请求/时间后重新初始化连接?
有帮助吗?

解决方案

基本上,是的,而且它节省了大量时间——设置套接字需要花费大量精力,对于 SSL 来说更糟。这就是为什么“keepalive”在过去被实施的原因。这有点违背 REST 理念,但它是一种性能优化。

有一件事是套接字是一种有限的资源。在真正频繁使用的环境中,您最终可能会没有任何套接字可供新连接使用。这是一件坏事。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top