2017-01-05 2 views
3

В настоящее время я разрабатываю приложение, в котором нам нужен какой-то запрос, чтобы поразить наш сервер как можно скорее. Чтобы ускорить процесс запроса, мы должны устранить рукопожатие (как это требуется дополнительно) и иметь постоянное соединение.Keep Alive не работает должным образом на iOS

Приложение использует структуру Alamofire сделать все запрос на наш сервер и настройка заключается в следующем:

У нас есть менеджер сеанса настройки с настройками по умолчанию и заголовок HTTP.

lazy var sessionManager: Alamofire.SessionManager = { 
    let configuration = URLSessionConfiguration.default 
    configuration.httpAdditionalHeaders = Alamofire.SessionManager.defaultHTTPHeaders 
    let manager = Alamofire.SessionManager(configuration: configuration) 
    return manager 
}() 

Менеджер сеансов является постоянным по всем запросам. Каждый запрос сделан, используя следующий код:

self.sessionManager.request(request.urlString, method: request.method, parameters: request.parameters) 
      .responseJSON { [weak self] response in 
    // Handle the response 
} 

request.urlString это адрес нашего сервера «http://ourserver.com/example»

request.method устанавливается на сообщение

request.parameters является словарь paramators

Запрос работает нормально и мы получаем действительный ответ. Проблема возникает из-за таймера keep alive, который устанавливается нашим сервером до 300 секунд. Устройство поддерживает соединение в течение максимум 30 секунд на Wi-Fi и почти мгновенно закрывает его по GSM.


Сервер отладки

Мы сделали некоторые отладки на нашем сервере и найдены следующие результаты

Тесты:

Тест 1:

  • iPhone подключается к Интернет через WiFi

Тест 2:

  • iPhone подключается к Интернету через 3G

Поведение:

  • обоих случаях: приложение делает HTTP/1.1 запрос к веб-серверу с «Connection: keep-alive»; Сервер (сервер ip = 10.217.81.131) отвечает «Keep-Alive: timeout = 300, max = 99»
  • Клиентская сторона (тест 1 - приложение через WiFi) отправляет TCP FIN на 30-й секунде, и соединение закрывается
  • клиентской стороны (тест 2 - приложение через 3G) отправляет немедленно (ноль секунд) запрос на TCP FIN после того, как он принимает HTTP/1.1 OK сообщение из его первого HTTP POST

тест 1 журналы на сервере сторона:

  1. В 23.101902 приложение делает HTTP/1.Запрос 1 POST на сервер с «Connection: Keep-Alive» enter image description here

  2. На 23.139422 сервер отвечает HTTP/1.1 200 OK с «Connection: Keep-Alive» и «тайм-аут = 300» (300 секунд) enter image description here

  3. Круглый-Trip-Time (RTT) сообщается как 333.82 мс (это подчеркивает предел погрешности мы имеем на следующие временные метки):

enter image description here

  1. Приложение, однако, закрывает соединение за 30 секунд (прибл. с учетом вариаций интернет-транспорта - разница между отметками времени 54.200863 и 23.451979): enter image description here

  2. Испытание повторяется многократно прибл. Время 30 секунд будучи всегда контролируется

Теста 2 бревна на стороне сервера:

  1. запрос HTTP/1.1 POST из приложения: enter image description here
  2. HTTP-КИ ответа сервера с донжоном -alive принимаются и установлена ​​на уровне 300 секунд: enter image description here
  3. RTT является на 859.849 мсек enter image description here

приложение закрывается сразу же соединение, где сразу же является 21.197918 - 18.747780 = 2.450138 секунд

Испытания повторяются при переключении с Wi-Fi на 3G и обратно с теми же результатами записывается.

Клиент отладки

Использование WiFi

Первая попытка (соединение установлено)

Optional(
[AnyHashable("Content-Type"): text/html, 

AnyHashable("Content-Encoding"): gzip, 

AnyHashable("Content-Length"): 36, 

AnyHashable("Set-Cookie"): user_cookieuser_session=HXQuslXgivCRKd%2BJ6bkg5D%2B0pWhCAWkUPedUEGyZQ8%2Fl65UeFcsgebkF4tqZQYzVgp2gWgAQ3DwJA5dbXUCz4%2FnxIhUTVlTShIsUMeeK6Ej8YMlB11DAewHmkp%2Bd3Nr7hJFFQlld%2BD8Q2M46OMRGJ7joOzmvH3tXgQtRqR9gS2K1IpsdGupJ3DZ1AWBP5HwS41yqZraYsBtRrFnpGgK0CH9JrnsHhRmYpD40NmlZQ6DWtDt%2B8p6eg9jF0xE6k0Es4Q%2FNiAx9S9PkhII7CKPuBYfFi1Ijd7ILaCH5TXV3vipz0TmlADktC1OARPTYSwygN2r6bEsX15Un5WUhc2caCeuXnmd6xy8sbjVUDn72KELWzdmDTl6p5fRapHzFEfGEEg2LOEuwybmf2Nt6DHB6o6EA5vfJovh2obpp4HkIeAQ%3D; expires=Sun, 08-Jan-2017 12:51:43 GMT; path=/, 

AnyHashable("Keep-Alive"): timeout=300, max=100, 

AnyHashable("Connection"): Keep-Alive, 

AnyHashable("X-Powered-By"): PHP/5.3.10-1ubuntu3.11, 

AnyHashable("Server"): Apache/2.2.22 (Ubuntu), 

AnyHashable("Vary"): Accept-Encoding, 

AnyHashable("Date"): Sun, 08 Jan 2017 10:51:43 GMT]) 

Вторая попытка (в течение 30 секунд, соединение все еще живы)

Optional([AnyHashable("Content-Type"): text/html, 

AnyHashable("Content-Encoding"): gzip, 

AnyHashable("Content-Length"): 36, 

AnyHashable("Keep-Alive"): timeout=300, max=99, 

AnyHashable("Connection"): Keep-Alive, 

AnyHashable("X-Powered-By"): PHP/5.3.10-1ubuntu3.11, 

AnyHashable("Server"): Apache/2.2.22 (Ubuntu), 

AnyHashable("Vary"): Accept-Encoding, 

AnyHashable("Date"): Sun, 08 Jan 2017 11:00:18 GMT]) 

Затем через 30 секунд соединение падает (FI)

Использование 3G

Первая попытка

Optional([AnyHashable("Content-Type"): text/html, 

AnyHashable("Content-Encoding"): gzip, 

AnyHashable("Content-Length"): 36, 

AnyHashable("Connection"): keep-alive, 

AnyHashable("X-Powered-By"): PHP/5.3.10-1ubuntu3.11, 

AnyHashable("Server"): Apache/2.2.22 (Ubuntu), 

AnyHashable("Vary"): Accept-Encoding, 

AnyHashable("Date"): Sun, 08 Jan 2017 11:04:31 GMT]) 

Затем соединение падает почти мгновенно.

+0

Не могли бы вы также зарегистрировать заголовки, которые поступают в ваше приложение с сервера? Обратите внимание, что некоторые прокси могут изменять заголовки keep-alive. – Sulthan

+0

Вы пытались использовать «Keep-Alive» вместо «keep-alive» в запросе клиента? Спецификация немного неоднозначна, но это может иметь значение. – dgatwood

+0

@Sulthan Я добавил заголовки, которые приходят в приложение с сервера в конце вопроса, в разделе «Отладка клиента». Я вижу, что на тестах wifi keep live имеет как таймаут, так и max, а на тестах 3g это не так. Интересно, это нормальное поведение. – zirinisp

ответ

1

Теперь, когда я просмотрел код во второй раз, я думаю, что вижу проблему. Основной класс NSURLSession по умолчанию игнорирует заголовок keep-alive, потому что некоторые серверы «поддерживают» его, но на практике сильно ломаются, если вы на самом деле пытаетесь его использовать, IIRC.

Если вы хотите, чтобы сессия поддерживала keep-alive, вы должны явно установить HTTPShouldUsePipelining в конфигурации сеанса на YES.

Обратите внимание, что до сих пор нет гарантии, что соединение будет оставаться в силе, в зависимости от того, насколько агрессивно iOS решает управлять радио, но по крайней мере у вас будет молитва. :-)

+0

Мы попытались установить HTTPShouldUsePipelining в true, и мы получим одинаковые результаты. – zirinisp