Синхронизировать PoolingClientConnectionManager или нет.

В моем приложении несколько IntentService подключаются / взаимодействуют с сервером Tomcat в случайные интервалы в зависимости от взаимодействия пользователя с приложением.

Я использую следующий синглтон для Http

public class CustomHttpClient { private static HttpClient customHttpClient; /** A private Constructor prevents instantiation */ private CustomHttpClient() { } public static synchronized HttpClient getHttpClient() { if (customHttpClient == null) { HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); HttpProtocolParams.setUserAgent(params,"Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83)" + " AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"); ConnManagerParams.setTimeout(params, 1000); HttpConnectionParams.setConnectionTimeout(params, 5000); HttpConnectionParams.setSoTimeout(params, 10000); SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schReg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params,schReg); customHttpClient = new DefaultHttpClient(conMgr, params); } return customHttpClient; } public Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } } 

Класс отлично работает, за исключением того, что он дает connectTimeOut всякий раз, когда два IntentService пытаются Http в одно и то же время или когда одно соединение выполняется, и устанавливается другое соединение.

Одним из очевидных улучшений в коде является замена устаревшего ThreadSafeClientConnManager с помощью PoolingClientConnectionManager.

Должен ли я synchronize здесь -> public static synchronized HttpClient getHttpClient()

Какая ошибка в Singleton вызывает connectTimeOut ?

Синхронизировать PoolingClientConnectionManager или нет?

Да и нет. Если вы хотите, чтобы getHttpClient() был одиночным (IMO – хорошая идея), вы должны сделать его потокобезопасным. Для этого требуется synchronized . Без synchronized двух потоков можно одновременно ввести блок if (поскольку customHttpClient == null является истинным для обоих потоков) и создать два экземпляра.

Но есть лучшие (как быстрее) пути без synchronized для создания потокобезопасных синглетонов. Например, мне нравится подход Singleton Holder .

Но независимо от того, какой синглтон вы используете здесь, вы не должны получать таймауты подключения. Он также должен работать, если вы используете новые экземпляры HttpClient для каждого потока.


Если произойдет таймаут соединения, один из ваших потоков не смог подключиться к серверу в течение установленного вами времени с помощью HttpConnectionParams.setConnectionTimeout(params, 5000); = 5 секунд.

Это может иметь несколько причин. Например, если вы находитесь на медленном и нестабильном подключении, может потребоваться больше времени, потому что может случиться, что ваше соединение мертво в течение нескольких секунд. Или если ваш сервер не может обрабатывать больше подключений либо из-за конфигурации (например, ограничение соединения на IP), либо потому, что аппаратное обеспечение не может обрабатывать больше, вы также можете увидеть эту проблему. В принципе, все, что мешает HttpClient отправлять и получать пакеты на / с сервера, может вызвать эту проблему. Означает, что ваша проблема связана либо с устройством, либо в сети, либо на сервере.

Я не знаю вашу настройку сети, но вы можете попытаться увеличить тайм-аут и посмотреть, не имеет ли это никакого эффекта. Например, AndroidHttpClient устанавливает эти таймауты на 60 секунд. Это намного больше, чем требуется, если вы находитесь в сети Wi-Fi и имеете стабильное соединение, но хорошо, когда соединение действительно слабое.

Вы также можете проверить, применяются ли другие настройки, которые AndroidHttpClient .

Настройка AndroidHttpClient ниже

 // Default connection and socket timeout of 60 seconds. Tweak to taste. private static final int SOCKET_OPERATION_TIMEOUT = 60 * 1000; // ---------------------------------------------------------------------- // HttpParams params = new BasicHttpParams(); // Turn off stale checking. Our connections break all the time anyway, // and it's not worth it to pay the penalty of checking every time. HttpConnectionParams.setStaleCheckingEnabled(params, false); HttpConnectionParams.setConnectionTimeout(params, SOCKET_OPERATION_TIMEOUT); HttpConnectionParams.setSoTimeout(params, SOCKET_OPERATION_TIMEOUT); HttpConnectionParams.setSocketBufferSize(params, 8192); // Don't handle redirects -- return them to the caller. Our code // often wants to re-POST after a redirect, which we must do ourselves. HttpClientParams.setRedirecting(params, false); // Use a session cache for SSL sockets SSLSessionCache sessionCache = context == null ? null : new SSLSessionCache(context); // Set the specified user agent and register standard protocols. HttpProtocolParams.setUserAgent(params, userAgent); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLCertificateSocketFactory.getHttpSocketFactory( SOCKET_OPERATION_TIMEOUT, sessionCache), 443)); ClientConnectionManager manager = new ThreadSafeClientConnManager(params, schemeRegistry); return new DefaultHttpClient(manager, params); 

Чтобы определить, где находится ваша проблема, вы можете заглянуть в свои журналы подключения к серверу и проверить, пытается ли устройство инициировать соединение, и если это так, если есть причины, по которым соединение не установлено. Если вы не видите попыток соединения, когда происходит тайм-аут, это скорее проблема устройства или сети.

Если у вас есть доступ к сети, к которой подключено устройство (= WiFi), вы можете проверить сетевой трафик, например, Wireshark по причинам, связанным с попытками подключения. Вы можете видеть это, если устройство отправляет запрос на соединение или нет.

И последнее, но не в последнюю очередь это может быть вызвано некоторыми из вашего кода. Если вы не найдете другого решения, попробуйте реализовать его с помощью HttpURLConnection и посмотрите, поможет ли это.

Intereting Posts