Всем привет!
На связи Никита — системный инженер из компании SЕMrush. Сегодня я расскажу вам о том, как перед нами встала задача обеспечить стабильность работы нашего сервиса semrush.com в Китае, и с какими проблемами мы столкнулись в ходе ее выполнения (учитывая местонахождение нашего дата-центра на восточном побережье США).
Это будет большая история, разбитая на несколько статей. Расскажу, как все это было у нас: от полностью неработающего сервиса из Китая, до показателей работы сервиса на уровне его американской версии для американцев. Обещаю, будет интересно и полезно. Итак, поехали.
Проблемы китайского интернета
Даже самый далекий человек от специфики сетевого администрирования хотя бы раз, да слышал о Великом Китайском Фаерволе. Ууу, звучит круто, да? Но что это такое, как оно работает на самом деле — вопрос довольно сложный. В интернете можно найти много статей, посвященных этому, но с технической точки зрения устройство этого фаервола нигде не описано. Что, впрочем, неудивительно. Признаюсь сразу, по итогам года работы я не смогу сказать точно, как он работает, но смогу рассказать о своих замечаниях и практических выводах. И начнем мы со слухов об этом фаерволе.
Есть много слухов об этом самом фаерволе. Давайте соберем основные и наиболее интересные из них в один список:
- Google, Facebook, Twitter и прочие подобные сервисы заблокированы и не работают в Китае.
- Любой трафик, идущий ЗА пределы Китая и В Китай, парсится и ограничивается с помощью машинного обучения (в случае подозрительного трафика), что сильно замедляет его (трафик), проходящий через границу.
- Китайские спецслужбы взломают любой зашифрованный трафик, идущий через их фаервол.
- VPN-туннели, IPSEC-туннели нестабильны, падают и постоянно блокируются.
- Чем проще шифрование, чем проще pass phrase, используемая для аутентификации/шифра трафика, тем быстрее он проходит китайский фаервол.
Вот, что нам удалось выяснить об этих слухах:
- Google, Facebook, Twitter и прочие подобные сервисы действительно заблокированы (ваш КО), но многие технические домены Google, например, не забанены и работают (тот же gstatic.com). Отсюда следует вывод: не стоит безрассудно выпиливать все подряд гугловые и прочие, кажущиеся заблокированными, ресурсы.
- Любой трафик, проходящий границу, действительно прибавляет к своему времени нешуточный delay. Посмотрите на два результата. Один сайт, одна страница, простой GET curl’ом. Первый замер из самого Китая (прекрасный город Шеньчжень). Второй замер снаружи из Гонконга (имеет суверенитет, и между ним и миром нет фаервола). Расстояние между городами по прямой примерно 30-40 км.
nikita@china-shenzhen:~# curl -o /dev/null -w@curl_time "https://www.semrush.com/info/ebay.com"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 381k 0 381k 0 0 71824 0 --:--:-- 0:00:05 --:--:-- 82832
time_namelookup: 0.004500
time_connect: 0.169342
time_appconnect: 0.723189
time_pretransfer: 0.723499
time_redirect: 0.000000
time_starttransfer: 1.532912
----------
time_total: 5.443407
----------
size_download: 390968 Bytes
speed_download: 71824.000B/s
nikita@china-hongkong:~# curl -o /dev/null -w@curl_time "https://www.semrush.com/info/ebay.com"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 319k 0 319k 0 0 2555k 0 --:--:-- --:--:-- --:--:-- 2573k
time_namelookup: 0.029366
time_connect: 0.030742
time_appconnect: 0.047310
time_pretransfer: 0.047388
time_redirect: 0.000000
time_starttransfer: 0.120793
----------
time_total: 0.124871
----------
size_download: 326755 Bytes
speed_download: 2616740.000B/s
Обратите внимание на time_connect. И в целом, вы видите результат: фаервол добавляет 4 лишних секунды, что чудовищно долго.
- VPN и IPSEC-туннели действительно часто падают. Об этом я расскажу чуть позже и подробнее. VPN-серверы, которые используются пользователями, со временем блокируются (обычно в течение суток после начала использования).
- Есть мнение, полученное от людей, проживающих в Китае, что чем проще шифрование трафика, тем быстрее он проходит через границу, потому что легко понять, что в нем нет ничего противозаконного. И точно также “чистый” трафик получает больше полосы пропускания и скорости прохождения, а “грязный” трафик, в котором ничего не разобрать, получает наоборот более медленный проход. Для примера я приведу curl до ifconfig.co по протоколу HTTPS и HTTP.
curl -o /dev/null -w@curl_time "https://ifconfig.co/"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 13 100 13 0 0 2 0 0:00:06 0:00:05 0:00:01 3
time_namelookup: 0.004305
time_connect: 0.397465
time_appconnect: 5.149305
time_pretransfer: 5.149393
time_redirect: 0.000000
time_starttransfer: 5.568847
----------
time_total: 5.568893
----------
size_download: 13 Bytes
speed_download: 2.000B/s
curl -o /dev/null -w@curl_time "http://ifconfig.co/"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 13 100 13 0 0 28 0 --:--:-- --:--:-- --:--:-- 28
time_namelookup: 0.004282
time_connect: 0.212457
time_appconnect: 0.000000
time_pretransfer: 0.212484
time_redirect: 0.000000
time_starttransfer: 0.450565
----------
time_total: 0.450620
----------
size_download: 13 Bytes
speed_download: 28.000B/s
Разница в 5 секунд на общее время загрузки 13 байт. При том, делая такой тест несколько раз, можно заметить, что GET на HTTP завершается в целом за одинаковое время каждый раз, в то время как по HTTPS сайт отвечает иногда за 3, 5, 10 и даже 17 секунд. Иногда случаются ошибки SSL:
Unknown SSL protocol error in connection to ifconfig.co:443.
Итак, что мы имеем:
- Проблемы, создаваемые китайским фаерволом, описанные выше.
- Пинги до внешних ресурсов и внутри туннелей периодически пропадают.
- Latency между двумя точками постоянно меняется, а зачастую она просто непредсказуема. Соединяя разные города/регионы, ты ожидаешь, что исходя из географического расположения регионов, задержка будет меньше, а получаешь ровно обратную ситуацию.
- Интернет и каналы связи работают то быстро, то медленно. Тут есть небольшая зависимость от времени суток и дня недели, но не всегда.
- DNS-запросы во внешний мир из Китая иногда превышают допустимый таймаут.
Картина вырисовывается просто “отличная”.
Датацентр, как я уже сказал, у нас на востоке США, а весь SEMrush состоит из десятков взаимосвязанных продуктов, бэкэндов, фронтэндов, баз данных, и все это в ДЦ и облаках. Перед нами, как командой системных администраторов, была поставлена задача малыми усилиями быстро начать работать в Китае.
Нам предстояло ответить на важный вопрос: можно ли обойтись малой кровью и решить все проблемы, связанные с китайским интернетом и фаерволом, на уровне сети/облаков/серверов?
Мы начали с получения ICP-лицензии.
ICP-лицензия
Для того, чтобы иметь возможность размещать свой сервис в пределах Китая (Mainland China) и проводить тесты, нужно сначала получить ICP-лицензию на домен.
Если пользовательский трафик вашего сайта терминируется в пределах Mainland China, и если у вашего домена нет лицензии ICP, ваш трафик будет блокироваться на стороне провайдера/хостинга. Интересно, что в ICP-лицензию вписывается конкретный провайдер, будь то Cloudflare или Alibaba Cloud. Поэтому, если вы получали ICP-лицензию для Cloudflare и размещали свой сайт у них, в последствии “бесшовно” переехать на Alibaba Cloud у вас не получится. Необходимо будет добавлять в эту лицензию еще один хостинг.
Получив ICP-лицензию на домен, мы смогли придумывать и реализовывать конкретные технические идеи и решения.
Тестирование решений
Но перед тем, как непосредственно создавать варианты стейджингов, крутить ручки, оптимизировать работу сайта и его скорость, нужно выбрать инструмент для его тестирования, чтобы видеть, какие наши действия улучшают или наоборот ухудшают работу сайта.
Наш инструмент для тестирования должен был соответствовать двум главным требованиям:
- он должен иметь возможность запуска тестов из Китая,
- он должен иметь браузерные тесты.
Так мы нашли Catchpoint! У них отличное покрытие точками тестирования по всему миру. В Китае через этот инструмент можно запускать тесты тоже из 100500 провинций. В каждой по несколько разных провайдеров + возможность делать Backbone-тесты (что-то типа виртуалки в датацентре) и Lastmile-тесты (максимально приближенные к пользовательским условиям, aka рабочая станция). Последний тип тестов стоит дороже.
Заключив годовой контракт (меньше нельзя), мы приступили к изучению инструмента. Признаться, мы были приятно удивлены его функционалом. Можно запускать:
- DNS-тесты,
- Web-тесты (браузерные, простой GET/POST, эмуляция мобильного клиента и т.д.),
- Транзакционные проверки (например, логин),
- API-тесты,
- Ping, traceroute, NTP и т.д.
Всего не перечислишь. И что самое главное, каждый тест можно довольно хорошо кастомизировать, добавив пачку заголовков и других параметров. На выходе получается огромное количество информации, полностью описывающей твой тест. Если говорить о самом интересном для нас (браузерные тесты), то результат включает в себя:
- Connect, Wait, Load, SSL, DNS time,
- TTFB, TTLB, Document complete, Render time, DOM load,
- Response (что-то близкое к Time To First Byte), Webpage Response (что-то близкое к Time To Last Byte),
- Любые percentile, Average, Median time
- И т.п.
Соответственно, все эти метрики отлично помогают видеть изменения и понимать, стало ли лучше. Мы, в основном, смотрели на Response, Webpage Response, Median, 75 и 95 Percentiles.
Важный вопрос, который витал в воздухе с самого начала: а можно ли верить Catchpoint? Отражает ли этот инструмент реальную скорость загрузки сайта в Китае из разных городов или же это просто какой-то тест в вакууме, не имеющий ничего общего с real user experience?
Это большая проблема, потому что находясь в России практически невозможно достоверно узнать, как работает сайт из Китая. Делая socks-proxy через виртуалку, на выходе получаешь загрузку сайта в течение пары минут, что для тестов просто неприемлимо, поэтому единственным вариантом ручного тестирования остается curl и простые GET из консоли с замером времени. Это помогает, потому что данный тест хорошо отражает скорость работы сетевого решения, а если есть еще и браузерные тесты, то совсем хорошо.
Позже мы сами съездили в Китай и убедились, что Catchpoint верить можно, он довольно точно отражает реальные показатели скорости работы.
Cloudflare China Network
Так как для основного домена semrush.com мы успешно используем Cloudflare, решили сразу попробовать их фичу под названием China Network. Данная опция включается только для Enterprise-сайтов по отдельному запросу и за отдельную плату. Также она доступна только для сайтов, имеющих соответствующую ICP-лицензию, в которой в качестве провайдера указан Cloudflare. После ее включения, для сайта становится доступным “китайский CDN” от Cloudflare — трафик из китайских регионов приземляется в ближайшие PoP (Points of Presence) CF, а дальше уже по его сетям или сетям провайдеров/партнеров доставляется до origin.
Схема данного тестового стенда представлена ниже.
Для нас это прекрасный вариант. Получается, что второй домен будет тоже за CF, что не прибавляет количество решений, используемых в компании, а также практически не усложняет инфраструктуру.
Мы запустили браузерные тесты, и вот что получилось:
Красные ромбики — это фейлы тестов. Фейлы снизу — DNS ошибки (resolve timeout). Фейлы сверху — таймауты.
Uptime: 86.6
Median: 18s
75 Percentile: 29.3s
95 Percentile: 60s
Медиана, после того, как убрали загрузку reCaptcha (сервис гугла, заблокированный в Китае), снизилась с 28 до 18 сек. Но все равно это ужасные показатели, если учесть, что такой же тест для semrush.com (из США) давал менее 10 секунд для 95% пользователей (из США) на ту же самую страницу (статика + динамика).
В каждый тест можно зайти и посмотреть Waterfall и другие более подробные параметры. Мы начали исследовать причины ошибок, и если для таймаутов все более менее понятно: интернет в Китае “то съезжается, то разъезжается”, из-за этого скорость коннекта и загрузки ресурсов из-за границы нестабильна и неодинакова, то DNS-ошибки нас сильно удивили. Мы обнаружили, что PoP у Cloudflare действительно находятся в Китае, адрес сайта резолвится в один anycast IP, но DNS-серверы используются американские, из-за чего DNS-запросы вынуждены проходить через границу, поэтому иногда они фейлятся.
Уточнив этот вопрос у CF, выяснилось, что своих DNS-серверов в Китае у них нет, а когда будет — пока неизвестно.
Поэтому мы решили потестировать только DNS Cloudflare и поменяли механизм работы Cloudflare для нашего сайта на режим “Только DNS”. Это такой режим, когда Cloudflare не проксирует трафик через себя, а значит, не предоставляет DDoS-защиты, CDN и прочие фичи, и работает в режиме обычного DNS-сервера.
Данный стенд схематично представлен на следующем рисунке. На рисунке учтены появившиеся знания о том, что DNS-сервера Cloudflare за фаерволом.
В Catchpoint мы запустили простые GET-тесты (не браузерные), которые показали очень много фейлов. Причиной их были все те же DNS ошибки.
Начали дебажить эти ошибки с помощью dig и обнаружили, что при первом запросе адрес определяется правильно, а при повторном запросе мы получаем каждый раз SERVFAIL и not found. Это с чего вдруг?
root@iZwz97n2wgbp61qucbfrjsZ:~# host semrushchina.cn
semrushchina.cn has address 220.170.186.192
Host semrushchina.cn not found: 2(SERVFAIL)
root@iZwz97n2wgbp61qucbfrjsZ:~# host semrushchina.cn
semrushchina.cn has address 220.170.186.192
Host semrushchina.cn not found: 2(SERVFAIL)
root@iZwz97n2wgbp61qucbfrjsZ:~# host semrushchina.cn
semrushchina.cn has address 220.170.186.192
Host semrushchina.cn not found: 2(SERVFAIL)
root@iZwz97n2wgbp61qucbfrjsZ:~# host semrushchina.cn
semrushchina.cn has address 220.170.186.192
Host semrushchina.cn not found: 2(SERVFAIL)
При запросе NS-серверов Cloudflare напрямую таких ошибок нет:
root@iZwz97n2wgbp61qucbfrjsZ:~# for i in `seq 1 2`; do host semrushchina.cn ray.ns.cloudflare.com.; done
Using domain server:
Name: ray.ns.cloudflare.com.
Address: 173.245.59.138#53
Aliases:
semrushchina.cn has address 220.170.186.192
semrushchina.cn has address 220.170.186.192
Using domain server:
Name: ray.ns.cloudflare.com.
Address: 173.245.59.138#53
Aliases:
semrushchina.cn has address 220.170.186.192
semrushchina.cn has address 220.170.186.192
Значит, проблема на стороне “локального” DNS-сервера или сервера провайдера.
Дальнейшее расследование показало, что SERVFAIL мы получаем на резолве AAAA-записи.
Оказалось, что при запросе у Cloudflare АААА-записи, которой в домене нет, Cloudflare отвечал А-записью, что является ошибкой и несоответствием RFC. Из-за чего локальному резолверу (x.x.x.x) это не нравилось, и он отвечал SERVFAIL. В логе ниже это поведение отчетливо видно:
root@iZwz97n2wgbp61qucbfrjsZ:~# dig -t AAAA semrushchina.cn @x.x.x.x
; <<>> DiG 9.10.3-P4-Ubuntu <<>> -t AAAA semrushchina.cn @x.x.x.x
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 55467
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;semrushchina.cn. IN AAAA
;; Query time: 334 msec
;; SERVER: x.x.x.x#53(x.x.x.x)
;; WHEN: Tue Aug 14 23:38:50 CST 2018
;; MSG SIZE rcvd: 44
root@iZwz97n2wgbp61qucbfrjsZ:~# dig -t AAAA semrushchina.cn @dana.ns.cloudflare.com.
; <<>> DiG 9.10.3-P4-Ubuntu <<>> -t AAAA semrushchina.cn @dana.ns.cloudflare.com.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 63944
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;semrushchina.cn. IN AAAA
;; ANSWER SECTION:
semrushchina.cn. 300 IN A 220.170.186.192
;; Query time: 185 msec
;; SERVER: 173.245.58.105#53(173.245.58.105)
;; WHEN: Tue Aug 14 23:43:03 CST 2018
;; MSG SIZE rcvd: 60
Мы отправили bug-репорт Cloudflare, и они это исправили через какое-то время. Оказалось интересно: на настоящий момент в Китае до сих пор нет поддержки IPv6, поэтому Cloudflare не мог выдавать там свой IPv6 адрес в ответе на запрос АААА-записи. В итоге все решилось так, что для Китая Cloudflare стал отвечать NODATA на такие запросы.
Так, ошибки DNS в тестах Catchpoint резко уменьшились, но не до конца. Таймауты тоже никуда не делись:
И мы начали искать другое решение.
В следующей части я расскажу, как мы тестировали китайское облако Alibaba Cloud, как с помощью небольшой "магии" Nginx мы смогли быстро создавать PoC (Proof of Concept) решений, как мы создавали Multi-Cloud решения, одно из которых в итоге очень сильно помогло ускорить работу сервиса из Китая.
Stay tuned!