在单身

时间:2018-05-22 19:26:15

标签: java scala apache-httpclient-4.x apache-commons-httpclient

我正在使用Apache Http Client 4.5.3并且目前正在重构一些代码。

目前我有一个单独的Util,它有几个方法,其职责是使用获取,帖子,补丁等来访问API。以前,我们一直使用HttpClientBuilder来构造CloseableHttpClient个对象对于每种方法的每次调用。大致上,Singleton的架构是这样的:

import com.google.gson.Gson
import org.apache.http.client.methods.{HttpGet, HttpPost}
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.{CloseableHttpClient, HttpClientBuilder}
import org.apache.http.util.EntityUtils
import org.json4s.DefaultFormats
import org.json4s.jackson.JsonMethods.parse

object ApiCallerUtil {

  case class StoreableObj(name:String, id:Long)
  case class ResponseKey(key:Long)

  def getKeyCall(param:String): ResponseKey = {
    implicit val formats = DefaultFormats
    val get = new HttpGet("http://wwww.someUrl.com/api/?value=" + param)
    val client:CloseableHttpClient = HttpClientBuilder.create().build()
    val response = client.execute(get)
    try {
      val entity = response.getEntity
      val entityStr = EntityUtils.toString(entity)
      parse(entityStr).extract[ResponseKey]
    } finally {
      response.close()
      client.close()
    }
  }

  def postNewObjCall(param:String, i:Long): Boolean = {
    val post = new HttpPost(("http://wwww.someUrl.com/api/createNewObj"))
    val client = HttpClientBuilder.create().build()
    post.setHeader("Content-type", "application/json")
    val pollAsJson = new Gson().toJson(StoreableObj(param, i))
    post.setEntity(new StringEntity(pollAsJson))
    val response = client.execute(post)
    try {
      if (response.getStatusLine.getStatusCode < 300) true else false
    } finally {
      response.close()
      client.close()
    }
  }

  //... and so on

}

关于如何使用它的注意事项 - 我们的系统中有许多类使用此Singleton Util来调用API。这个Singleton将经历短时间的大量使用,其中几个班级将以频繁的频率(在几分钟时段内达到1000次)进行相同的呼叫,以及在很长一段时间内多次击中的时段(每小时一次或两次),或者一次几个小时。此外,它所点击的所有网址都会以相同的网址开头(例如www.someUrl.com/api/

但是我想知道实现它是否有意义,val client = HttpClientBuilder.create().build被调用一次作为对象内可访问变量的私有val。这样,它只在对象实例化时创建一次。这是我暂停的地方,Apache documentation确实说了这两件事:

  

1.2.1。 [Closeable] HttpClient实现应该是线程安全的。建议重用此类的相同实例   用于多个请求执行。

     

1.2.2。当不再需要[Closeable] HttpClient实例并且即将超出范围时,关闭它是很重要的   连接管理器,以确保所有连接保持活动状态   管理器关闭并由这些连接分配系统资源   被释放。

我已阅读了大部分文档,但对以下内容没有一个可靠的答案:

  1. 将CloseableHttpClient实例作为私有全局变量是否有任何风险?我担心一些东西可能会被关闭,如果它已经过时,并且我必须在一段时间之后将其树脂化,或者,在大量使用的情况下,它会造成太大的瓶颈。根据上面的#1.2.2,变量将“永远”超出范围,因为它是一个单例对象。但是因为我正在构建客户端并且在我去的时候传递HttpRequest个对象,而不是仅仅在请求之外将它连接到API,所以它似乎无关紧要。

  2. 由于使用ApiCallerUtil单身人士的性质,或许明智地使用他们的HttpClientConnectionManager或。{ PoolingHttpClientConnectionManagerwww.someUrl.com/api/保持稳定联系?性能提升是否值得?到目前为止,目前的实施似乎没有任何严重的性能缺陷。

  3. 感谢您的反馈!

1 个答案:

答案 0 :(得分:2)

  1. 没有(根据我15年以上的HttpClient经验)。

  2. 这实际上取决于各种因素(TLS会话握手的开销等)。我想有人真的想确保通过持久连接执行一系列相关请求。在长时间不活动期间,可能想要从连接池中驱逐所有空闲连接。这有一个额外的好处,可以减少遇到陈旧(半封闭)连接问题的可能性。