2014-06-29

Об асинхронном

Тамтэк снова тестирует NoSQL. А я тут что-то вспомнил замечания, высказанные после Highload++ Михаилом Епихиным. Про тестирование асинхронными клиентами...


Давным давно, когда Apache httpd был еще версии 1, веб-сервера создавали по новому процессу на каждое новое соединение. Ну и классический CGI так же работает. Ну и inetd (если кто помнит и включал его), позволяет для входящего соединения запускать произвольный процесс (да хоть скрипт) для его обслуживания. Теперь от запуска процессов отказались. Процесс запускается долго. Процесс ест много ресурсов. Некошерно.

Теперешний Apache httpd создает по новому потоку на каждое новое соединение. Потоки легче процессов. Потоки можно насоздавать заранее (тот самый пул). Уже лучше. Но потоки тоже требуют заметных ресурсов, в основном на переключение контекстов (процессору нужно сохранить все регистры в стек, переставить указатель команд, очистить свой кэш и прочее и прочее). Отсюда возникает пресловутая 10k problem. Ну нельзя таким способом обслужить десятки тысяч одновременных запросов. Никакие многоядерные процы (разумной стоимости) не потянут десятки тысяч потоков.


Ну а теперь у нас есть всякие Nginx (почти 10 лет уж) и Lighthttpd. Они работают в одном потоке (ну, точнее, в паре-тройке, чтобы все ядра ЦПУ загрузить). И побеждают десятитысячную проблему. Как?

Весь секрет в системных вызовах вроде epoll. Обычные системные вызовы (по работе с сетью или с диском) — блокирующие. Поток выполнения блокируется (перестает планироваться на ЦПУ), пока нет новых данных (из сети или диска). Epoll — неблокирующий. Один серверный поток мониторит (собственно, делает poll) сразу много дискрипторов (сокетов и файлов). Тупо опрашивает в бесконечном цикле: а есть ли какие-то данные? (Когда данных нет ни в одном дискрипторе, поток может быть так же заблокирован, так что этот цикл не жрет ЦПУ). И если эти данные есть, маленькая порция, они передаются в другой дискриптор (от диска в сеть, например).


Собственно, тут нет ничего особо нового. Все ГУИ с самого начала строятся подобным образом. Есть бесконечный цикл обработки событий. Пока событий (движений или кликов мыши, нажатий клавиш клавиатуры) нет, мы ничего не делаем. Когда события есть, мы быстро их обрабатываем (в обработчиках) и снова уходим в цикл. Просто теперь этот же принцип применили и к обработке сетевых событий.

У этого подхода есть ограничения. Собственно, все руководства по ГУИ про них пишут. Поток один и от скорости его выполнения зависит скорость обслуживания всех событий. Если обработчик события о чем-то задумается (или, о ужас, будет выполнять блокирующие операции), мы потеряем в скорости (ГУИ зависнет). Поэтому делать серьезных вычислений или обращаться к другим ресурсам в обработчиках нельзя. В ГУИ для этого рекомендуют заводить отдельные потоки и уже оттуда передавать результаты длительных операций в основной поток (чтобы обновить УИ). В случае веб-серверов вроде Nginx мы ограничиваем работу сервера только обслуживанием статики (т.е. с одной стороны — сокеты, с другой — файлы). А динамику проксируем на другой, классический сервер (т.е. передаем другому процессу).


Что нам мешает обслуживать динамику на том же сервере? То, что классические языки (веб) программирования поддерживают многопоточную модель (с разделяемыми данными, семафорами и прочим), но не умеют асинхронную обработку. Но все меняется прямо на глазах.

Подход номер раз (по популярности). Обрабатываем асинхронные события обработчиками-колбэками. То бишь на каждое событие по функции (а то и по две — вторая для ошибок). Таков старый добрый питоновый Twisted. Таков нынче популярный Node.js. Все просто, эффективно и функционально. Но описание колбэков колбэков на колбэки чисто визуально выглядит ужасно. И отлаживать это дело жутко, ибо стектрейс начинается где-то с того самого главного цикла и вовсе непонятно, какое событие вызвало ошибку (впрочем, я не знаю, возможно такая проблема с любым асинхроном).

Можно замаскировать колбэки в футуры (они же деферы и промисы). Маскируем асинхронные вызовы под синхронные. Делаем вызов, получаем не настоящий результат, а футуру. Продолжаем выполнение нашего потока, а где-то в фоне происходит что-то, что мы запросили. Позднее, когда нам таки понадобится актуальное значение, мы возьмем его готовенькое из футуры. Очень неявная асинхронность. Плохо, что если мы попросим значение слишком рано, мы таки заблокируемся в его ожидании (впрочем, можно явно cпросить футуру о готовности данных, неблокирующим вызовом). Получается не совсем честно. Хотя выглядит сильно привычнее обычным программистам.


Подход номер три. Акторы (они же легковесные процессы). Это наши любимые Erlang и Go. Это одноименная библиотека в Scala, которая стала частью языка. Это другие подобные библиотеки для других языков. Полностью меняем парадигму параллельного программирования. Не потоки, а акторы. Не вызовы функций или методов, а посылка сообщений. Не разделяемая память, а иммутабельные данные и посылка сообщений. В результате у среды исполнения (или библиотеки) появляется свобода распоряжаться аппаратными потоками выполнения, планировать выполнение акторов, поллить системные события, запускать акторы по приходу сообщений и многое другое. Все совсем по-другому, но наиболее эффективно.


Но асинхронным может быть не только сервер, но и клиент. Один клиентский поток флудит запросы с максимально возможной скоростью, не дожидаясь ответов. Когда таки приходят ответы, он их обрабатывает асинхронно. В случае теста СУБД, нам вообще нужно лишь узнать успешность выполнения и записать время, прошедшее от отправки запроса. Можно отправить громадное количество запросов. Ух.

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

Если сервер у нас асинхронный, то в рамках одного соединения мы можем слать несколько запросов и асинхронно получать ответы (протокол взаимодействия тоже должен быть асинхронным). Чем мы тут ограничены, кроме CPU на клиенте и сервере? Пожалуй, размером очереди запросов (на сервере как минимум), она, к сожалению, не может быть бесконечной. А значит, начиная с какого-то момента запросы будут возвращаться с ошибкой.

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


А какие сервера у нас асинхронные? Как внутри, так и на уровне протокола?

MongoDB — совсем нет. И по потоку на каждое клиентское соединение создается. И блокировки на совместный доступ к данным. И десятитысячная проблема встает во всей красе.

RethinkDB — это такая передуманная Монга. С асинхронными внутренностями и MVCC для хранилища. Но API манипулирует классическими курсорами, а операции всегда возвращают результат или ошибку. Синхронный протокол?

FoundationDB — совсем новое key-value хранилище с упорядоченными ключами и транзакциями. Внутренности асинхронные. Операции возвращают футуры! Оно?

Требуется дальнейшее исследование...

2014-06-15

Об Израиле

Продолжу публикацию путевых заметок из Жуйка. На этот раз отпуск всей семьей в Израиле в июне 2013.


Гуглокарты не позволяют сохранить для оффлайнового использования территорию Тель-Авива. Так и пишут: Нельзя сохранить эту область.
Кажись, дело все в западном берегу Иордана. Близко он там.

OSM. Простите, но латинская транслитерация местных географических названий нифига мне непонятна.


Электричка за 100 шекелей от Тель-Авива до Наарии. Тихо. Кондиционер. Стойка для багажа у дверей. Халявный вайфай.

Прокатили чуток на автомобиле. Знаков много. Скорость везде ограничена явно, в населенных пунктах — аж 30. Есть знак — домик в кружочке.
Дороги ровные. Все бордюры скошенные, чтобы можно было безболезненно наскочить на них. Очень много кольцевых развязок (где главное — кольцо) или ответвлений для поворота направо. Везде разметка. Ошибок типа заехать в не свой ряд или развернуться там, где разворачиваться нельзя сделать невозможно. И почти нет светофоров.
Треть дороги по ширине отделена желтой разметкой. Говорят — для велосипедистов.
Впрочем, это все на севере, возле Нагарии, типа сельская местность.

В каждой квартире есть выделенная комната-«бомбоубежище». Тридцатисантиметровые бетонные стены. Стальные ставни, стальная дверь.
Все серьезно. И хоть раз, но все пользовались.


Перфекционизмом и не пахнет. Все магазинчики грязные ровно настолько, чтобы не вызывать отвращение. Домики обшарпаны тоже в той же мере.
Мэр чинит дорогу только перед выборами. Детская площадка, запрещенная экологами, так и стоит закрытой второй год.
Везде, где видел работающих (на улице, в магазинах на раскладке товаров), работают они совсем не спеша и вполне не прочь поговорить о политике и чем-нибудь подобном.
Пожалуй, можно назвать это прагматизмом.

Искупался в Средиземном море. Впервые в море искупался. Сгорел, хотя и мазался.
Разницы в плавании в соленой воде (относительно пресной) не заметил. Хотя на вкус вода отвратительная, и, если не смыть, щиплет глаза.

Дома — из камня. Белые, квадратные, с плоской крышей.
На крышах стоят баки с водой, нагреваемые солнцем. Сколько квартир — столько и баков. Это — естественный источник горячей воды. А когда не хватает солнца, можно включить электронагреватель.


Удивительные разговоры тут можно услышать на русском языке.
Любят разговаривать про политику: про отношения Израиля с ближайшими соседями и про развал СССР.
Любят обсуждать, кто чем сколько болел, сколько детей и от кого родил, и насколько эти дети евреи.
Любят вспоминать свою жизнь за пределами Израиля. Из этой серии повеселила история одной дамы, которая привезла из России дубленку и зимние сапоги, чтобы не мерзнуть израильскими зимами, сидя перед телевизором.
(Подслушано случайно, в процессе дремоты на пляже)

Как можно читать на этом языке?


Раньше доча уже смотрела своих любимых даш-путешественниц и диегов на русском, английском и испанском, просто блуждая по ютубам. Теперь смотрит на иврите. И ничуть не смущается.

Телефонные разговоры тут не бывают короче трех минут.

Не могу отличить на слух арабский от иврита. К стыду своему.

У арабов очень веселые национальные песни. Нужны лишь ладоши, ритм, и вот группа подпитых волосатых мужиков, расположившихся под соседним зонтиком, орет свое, родное.

Родилась гипотеза, почему наиболее непокорные народы живут в гористой местности. Просто на равнине все конфликты решаются тем, кто быстрее. А в горах проявлять непокорность можно гораздо более разнообразными способами.


Как отличить еврейскую деревню от арабской? Точнее мусульманской, а то бывают даже арабы-христиане. В мусульманской деревне торчит один-два минарета.
А еще в арабских деревнях очень много недостроенных домов. Они так от налогов укрываются.

Странная тут мода разговаривать по сотовому. Телефон не прижимается к уху, а держится в сантиметре-двух.
Можно понять, учитывая, что ухо в таком климате всегда потное и липкое, а значит, заляпает экран дорогого айфона.

Про железные дороги и автобусы Израиля — ровно полтора убогих приложения в гуглоплее. Хотя вот та же схема ЖД сообщения очень похожа не схему метро, разве что поезда ходят не каждые две минуты, а раз в час. В общем, ниша свободна.

Железные дороги тут левосторонние. И на тепловозной тяге. Встречаются двухэтажные вагоны.

Старый Иерусалим — это такой большой кусок камня, сложенный из кусочков, колонн и арок самого разного возраста: от дофигаскольколет до нашей эры до английских 1930х годов.


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

У любого камня, у любой верхушки или любой дырки в скале тут найдется история в пару тысячелетий. Именно этот камень будет упомянут в Торе, Библии и Коране.
Не знаю, возможно, так в любых туристских местах.

Моря.
Средиземное. Весьма бурное. Соленое. Теплое. Каменистый берег делает возможным купание только в специально оборудованных местах. Волны — классные, но до серфинга не дотягивают.
Красное. Чуть солонее. Холоднее. Очень прозрачное. Всюду растут кораллы, так что зеленые блюдут любой клочок берега. Купаться из экологических соображений можно только в специально отведенных местах. Ну и не заплывать сильно далеко, чтобы случайно не пересечь границу с соседними государствами :) Зато, поныряв с маской, можно своими глазами увидеть всех этих разноцветных коралловых рыбок.
Мертвое. Как известно, чертовски соленое. На вкус не пробовал, ибо явно лизать побоялся, а нырять и запрещено, и не очень-то и хотелось. Очень теплое. Все что можно делать — лежать на воде кверху пузом.
Кинерет (Кинеры, Галилейское море). Пресное. Громадное озеро. Есть дикие пляжи. Хороший прибой. Народ катается на виндсерфингах. Мне больше всего понравилось.


Почему-то все экскурсоводы любят показывать границы. Таким образом, я обозрел границы с Ливаном, Палестинской Автономией, Иорданией, Египтом и морскую границу с Саудовской Аравией.

Посетил Эйлат. Самый южный город Израиля. Почти целый день туда на автобусе, почти целый день обратно. Две ночи и полтора дня — там.
Покупался в Красном море. Посмотрел на кораллы и рыбки. Почувствовал, что такое плюс 38 по Цельсию. Поругался на аэропорт под окнами отеля, да еще и с взлетающими винтовыми самолетами.


Раньше я никак не мог понять, зачем лежать спиной кверху на солнышке, если можно купаться, и зачем купаться в бассейне при отеле, если рядом — настоящее море. Теперь начал сам так поступать и понимаю :(
Потому что при +38 силы есть только на то, чтобы лежать, а не купаться. И лучше лежать в номере с кондиционером, но раз уж выбрался на пляж, то лежать хотя бы в тенечке.
Ну а купаться в бассейне более приятно. И понырять нормально можно, и вода глаза не щиплет и не противная на вкус.
Старею.

Типичный израильский перекресток выглядит так. Если это не кольцо.
Ответвление для поворота направо. Поворачивать можно всегда, только пропустить пешеходов и транспорт с других направлений. Мигает единственный желтый с силуэтом пешехода, предупреждает.
Для направления прямо — отдельный светофор, помеченный предписывающим знаком «Движение прямо». Для поворота налево — тоже отдельный светофор, помеченный знаком «Движение налево». В нем в виде стрелки — только зеленый сигнал. Никаких боковых секций. Выглядит это странно: подъезжаешь к перекрестку, а там два светофора.
Однако путаницы не возникает, потому что прямо, налево, направо — это разные полосы движения, четко выделенные разметкой и специальными бугорками на разделительной, призванными воздействовать на пятую точку водителя.
Разметка очень подробная. Знаков "Направления движения по полосам" нет, зато нарисованы здоровенные стрелки прямо посреди каждой полосы: куда можно поворачивать и когда перестраиваться. Бывает, даже размечены траектории левых поворотов.


Тут можно выпить чуток пивасика, прежде чем сесть за руль.
Ремнями пристегиваются все. Но, например, водитель автобуса не требует от пассажиров быть пристегнутыми, несмотря на наличие ремней.
Вообще видел, что зверствуют только насчет парковки. Да и то, включил аварийку, сидишь за рулем — ну и стой где попало хоть полчаса.
Ну и в субботу не штрафуют.

Почему во всем мире на знаке «Движение без остановки запрещено» написано STOP, а в Израиле нарисована поднятая ладонь? Потому что евреи читают справа налево и могут прочесть STOP оскорбительно неправильно.

На Мертвом море Билайн радостно поздравил меня с прибытием в Иорданию. А минутой позже — с возвращением в Израиль.

На каждом посту автотранспорт встречает улыбающаяся девушка в форме и с автоматом.
Посты стоят на въездах с территорий Бэ (где разрешается движение палестинских автомобилей) на основную территорию Израиля. Вокруг и в самом Иерусалиме постов этих — дофига.

После посещения Иерусалима становится интересно читать статьи Википедии религиозного содержания.


На линиях электропередач (коих тут тысячи) висят красные шары. Есть несколько гипотез, что это.
Чтобы не замыкало провода при сильном ветре. Маловероятно, ибо шары нанизаны только на один провод и довольно редко.
Чтобы линии электропередач было видно пилотам пролетающих самолетов и вертолетов. Тоже странно, ибо кроме ВВС США в районе Мертвого моря вряд ли кто летает так низко.
Чтобы уравновесить провода по обе стороны от поддерживающей опоры, а также избежать резонансных колебаний проводов и опоры. Звучит наиболее солидно, однако не понятно, почему так не делают в России.
Комментаций от @Rondo: Скорее всего это маркеры для пилотов, правда знания на эту тему у меня всего из одной статьи, да и то сами-знаете-кого tema.livejournal.com.

Выдвигаюсь в сторону родины.

Ну здравствуй, Россия.

Аэропорту Бен-Гуриона — минус 500 в карму за чудовищную очередь на досмотр и регистрацию. Улетающие из Израиля, имейте в виду, что в аэропорту нужно быть за три часа до рейса.
И это именно контроль безопасности аэропорта, еще ДО регистрации.
Сам досмотр не сильно напряг. У мну только пролистали кучку одинаковых книжек про МонгоДБ, которые я стащил на конференции. Полуторачасовая очередь напрягла. Там из очереди вытаскивали пассажиров, начинающих опаздывать на свой рейс. Такие очереди я видел только в JFK, да и то по прилету, а не на вылет.

Оказывается, за две недели пассажиром я привык к израильским дорогам. Вернулся в Роиссю и ужаснулся. Где разметка? Где нормальные развязки? Откуда пробки? Чо, блин, за ямищи на дорогах? Почему кольцо — не главная?

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


Фоточки
Гуглоистория