?

Log in

No account? Create an account

Стой под стрелой

Поступки и мысли, о которых могу вспомнить не краснея

Категория: дети

Zookeeper
усы2
tonsky

Поручили наркоману черепах в зоопарке стеречь. Он открыл дверь в загон, а они КАААААААК ломанутся!
Я точно не знаю, для кого и кем создавался ZooKeeper и как его правильно готовят, но если верить хайпу, то это такая система для обеспечения мутабельного стейта в кластере. Сервис, обеспечивающий всем нодам согласованное и постоянно-доступное (available) представление о происходящем.

Идея была такая, что они очень много усилий вложили в то, чтобы это работало, один раз сделали и теперь все могут выдохнуть. Версия 3.4.5, уж не знаю что там было в 1.0 или 2.0, страшно. Да что там, еще в 3.3.3 важные смысловые баги были, а вплоть до 3.4.0 он логами засирал диск вусмерть.

API Зукипера очень низкоуровневый. Чтобы что-то полезное сделать, надо придумывать и на бумажке сидеть рисовать как это будет работать. Предполагается, что это на откуп разработчикам recipes, которые заиспользуют платформу и напишут один раз корректный алгоритм на каждый случай. Это ставит крест на идее кроссплатформенности Зукипера, потому что реально рецепты пишут, кажется, только на java, да и то как-то не шибко спешат ими делиться.

Протестировать это, естественно, непросто, ведь тестировать надо на ситуации вроде падения, замедления, протухания серверов и коннектов до кластера Зукипера. И всё это нужно умудряться вставить в нужные места своего приложения, например, вот тут прячется рейс:
  (when-not (exists? zk "/path")
    (create zk "/path))
Для системы, обещающей вам согласованное состояниие, не дать метода вытащить поддерево за один вызов — это грустно. Если я сначала получу `children "/path"`, а потом начну вытаскивать каждого child, то пока я это делаю, их состав может поменяться. В итоге у меня будет размазанный по времени, несогласованный view поддерева, если кто-то в это время туда писал. Я согласен, что можно придумать задачи, когда это perfectly ok, но иногда ведь и нет.

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

Исходный java-клиент это вообще труба, надо сразу идти за Netflix Curator (его недавно забрал Апач и теперь даже исходники хрен скачаешь), но и с ним жизнь не сахар. В исходном клиенте ссылка на Zookeeper могла в любой момент перестать быть валидной (коннект сдох), и надо было как-то идти и всем во всех местах, кто ее уже использует, дружно ее пересоздавать. А, или вот, если вы сделали connect, нельзя сразу начинать его использовать, надо асинхронно подождать события sync-connected. В кураторе просто нужно следить за переходами между стейтами и аккуратно их обрабатывать (стейт-машина, да). Ох.

Есть и совсем глупые баги. Например, есть понятие эфемерных znodes, они ассоциируются с tcp-коннектом и стираются, если клиент сдох. Для service discovery хорошо, вот мол я, используйте меня по такому-то адресу, а если я пропал, нода сама удалится. Так вот, z-нода удаляется после таймаута, и если клиент сдох, а потом перезапустился и создал z-ноду еще раз (мол, я снова живой), то z-нода все равно удалится, когда первая сессия протухнет. То есть я живой и вот он, ноду создал, а она потом возьми и исчезни.

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

А чего душа просит? В первую очередь, умного клиента. Идея о том, что нужно предоставлять максимально кондовое API и клиента, состоящего из сгенеренных thrift-заглушек, она иногда правильная (потому что гибкая), но только не в случае распределенной системы. В распределенной системе клиент сам является компонентом, и рассчитывать на то, что юзеры понапишут правильных стейт-машин по переключению коннектов и обработке исключений — не стоит. Они скорее будут страдать от собственной тупости (а мы все неидеальны), отсутствия времени и нефундаментального подхода (все-таки не все FoundationDB пишут), чем обработают все случаи взаимодействия с API правильно.

Во-вторых, хочется получать consistent view одной фиксированной версии. Пусть она уже десять раз устарела, пока я ее скачивал, но она хотя бы будет непротиворечива блин. Это все делается на иммутабельности и merkle trees, what’s the problem?

В-третьих, больше атомарных операций: compare-and-set в принципе есть, а вот что-нибудь для работы с коллекциями, поддиректориями там, check-and-add и подобных. Возможно даже, просто транзакций. Поскольку мы над согласованным состоянием работаем, я не очень представляю, как без этого писать и что-то там гарантировать, только надеяться.

В-четвертых, идемпотентные операции. Мне как-то не сильно хочется думать о том, где я был и куда что добавил, лучше перестраховаться, чем недостраховаться.

В-пятых, больше стабильности и декларативности в клиенте. В конце концов, если мы декларируем себя как «последнее и окончательное решение проблемы шареного стейта», то не должно возникать ситуаций, когда существование моей эфемерной ноды зависит от того, правильно ли я обработал все ситуации потери коннекта и переподключения. Нет, если я сказал, что вот он я и я предоставляю сервис, то все должны меня видеть независимо от того, как и когда колбасит моё соединение, сколько раз я переподключался, перезапускался или не успевал ответить на heartbeat. Если я сказал, что мне интересно поддерево /jobs, я хочу получать новую информацию об этом дереве независимо от того, существует оно в момент моей просьбы, или будет создано позже, или его двадцать раз добавят-удалят, или Зукипер грохнут, остановят и всю память ему сотрут. У нас же и клиент, и сервер — все умные, почему я вообще по регэкспу не могу на множество путей подписаться? Этот пункт вроде бы решается на уровне умного клиента и даже оформляется как recipe к текущему zookeeper.

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

Наша конечная цель — чтобы каждый мог писать нетривиальные алгоритмы, включающие оперирование распределенным состоянием (recipes), и это не требовало бы сверхусилий, багоопасных стейт-машин и месяцев ловли блох в продакшне. То есть концепция не в том, чтобы крупная компания вляпалась в Зукипер и понаписала опенсорсных рецептов (на всех никогда не хватит), а в том, чтобы это могли делать не сверх-люди, и не слишком отвлекаясь от основного бизнеса.

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

Вот, вместо того, чтобы google reader клиентов переписывать или революцию в todo листах делать, может замутил бы кто, а? Там, глядишь, и Апач купит за бусы и ракушки, всё-таки стартап.

Переключение раскладки CapsLock-ом для Мака
tonsky
Зачем: КапсЛок — бесполезная клавиша в очень удобном месте. Переключать раскладку одной кнопкой очень удобно.

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

1. Скачиваем PlistEditPro.

2. Открываем с его помощью файл ~/Library/Preferences/ByHost/.GlobalPreferences.000d-что-то там. Учтите, что это скрытый файл, так что так просто его в диалоге не выберешь, проще из терминала:


  cd ~/Library/Preferences/ByHost
  /Applications/PlistEdit\ Pro.app/Contents/MacOS/PlistEdit\ Pro .GlobalPreferences.2ED2F52A-AEF9-56EE-A155-15190BFB7C5F.plist


3. Находим или добавляем раздел com.apple.keyboard.modifiermapping и дописываем туда маппинг 0 → 5 (CapsLock → KeyPad0, см. также БОНУСЫ):

<key>com.apple.keyboard.modifiermapping.1118-219-0</key>
<array>
  <dict>
    <key>HIDKeyboardModifierMappingDst</key>
    <integer>5</integer>
    <key>HIDKeyboardModifierMappingSrc</key>
    <integer>0</integer>
  </dict>
</array>


4. Перелогиниваемся.

5. Идем в System Preferences и ставим комбинацией на переключение раскладки CapsLock (он теперь при нажатии будет генерировать нажатие KeyPad0 — тоже не самая востребованная кнопка).

БОНУСЫ


1. Можно обойтись и без PlistEdit Pro:

  plutil -convert xml1 -o keys-xml.plist .Global…
  vim keys-xml.plist
  plutil -convert binary1 -o .Global… keys-xml.plist


2. Список всех кодов, которые можно перемапить:

None:         −1 (этим можно отключать кнопки)
Caps Lock:     0
Left Shift:    1
Left Control:  2
Left Option:   3
Left Command:  4
Keypad 0:      5
Help:          6
Right Shift:   9
Right Control: 10
Right Option:  11
Right Command: 12

Я не исследовал, возможно там и все остальные кнопки есть.

Навеяно Домом-2
tonsky
Сегодня имел счастье побыть с собой наедине и, чтобы чем-нибудь себя занять, начал выдумывать всякие глупости. Некоторые из них я решил вылолжить здесь. Они имеют форму рассказа, а точнее -- пересказа увиденной мной вчера серии телепроекта Дом-2. В вольном изложении и с элементами художественного вымысла. Итак.

читатьСвернуть )