Я использую 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.Этот синглтон будет проходить через короткие периоды интенсивного использования, когда несколько классов будут нажимать на одни и те же вызовы с большой частотой (до @ 1000 раз в течение нескольких минут), а также периоды, когда он срабатывает несколько раз в течение длительного периода времени (один или два раза в час) или совсем не часами.Кроме того, все URL-адреса, которые он просматривает, будут начинаться с одного и того же URL-адреса (например, www.someUrl.com/api/
)
Но мне интересно, имеет ли смысл реализовывать его, когда val client = HttpClientBuilder.create().build
вызывается один раз как частный valдля доступной только для объекта переменной.Таким образом, он создается только один раз, при создании объекта.Вот где я делаю паузу, в документации Apache говорится две вещи:
1.2.1.[Закрыть] Реализации HttpClient должны быть поточно-ориентированными.Рекомендуется повторно использовать один и тот же экземпляр этого класса для выполнения нескольких запросов.
1.2.2.Когда экземпляр [Closeable] HttpClient больше не нужен и собирается выйти из области видимости, важно закрыть его диспетчер соединений, чтобы убедиться, что все соединения, поддерживаемые менеджером, закрыты и системные ресурсы, выделенные этими соединениями, освобождены.
Я прочитал большую часть документации, но не имею четкого ответа на следующие вопросы:
Есть ли риск того, чтоЭкземпляр CloseableHttpClient как частная глобальная переменная?Я беспокоюсь, что что-то может быть закрыто, если оно устарело, и что через некоторое время мне придется его осилить, или, в случае интенсивного использования, это создаст слишком много узкого места.Согласно приведенному выше п. 1.2.2, переменная «никогда» не выйдет из области видимости, поскольку это одноэлементный объектНо поскольку я собираю только клиента и передаю ему объекты HttpRequest
, а не подключаю его к API за пределами одного запроса, кажется, это не имеет значения.
В связи с тем, как используется этот ApiCallerUtil
Singleton, было бы разумно использовать их HttpClientConnectionManager
или.PoolingHttpClientConnectionManager
для поддержания постоянного соединения с www.someUrl.com/api/
?Будет ли увеличение производительности того стоить?Пока что текущая реализация не имеет каких-либо существенных недостатков в производительности.
Спасибо за любые отзывы!