Устройство идентификатора процесса
В статье описывается, каким образом обеспечивается прозрачность идентификаторов процессов в erlang-кластере
Распределённость Erlang базируется в первую очередь на прозрачности идентификаторов процессов. Другими словами, мы можем отправлять сообщение процессу на другую ноду, зная только его идентификатор.
Рассмотрим, из чего же состоит этот идентификатор. Для начала, сериализуем его в последовательность байтов с помощью функции term_to_binary/1:
$ erl -sname valhalla@localhost (valhalla@localhost)1> Pid = pid(0,15,0). <0.15.0> (valhalla@localhost)2> Pb = term_to_binary(Pid). <<131,103,100,0,18,118,97,108,104,97,108,108,97,64,108,111,99,97,108,104,111,115,116,0,0,0,15,0,0,0,0,3>>
Разберём получившийся бинарник по частям:
- 131 — метка того, что этот бинарник является ерланговским термом
- 103 — метка типа терма, идентификатора процесса
- 100 — метка типа терма, атома, содержащего в себе имя ноды, на которой находится процесс
- <<0, 18>> — два байта, длина атома (в данном случае 18 байтов)
- <<118,97,108,104,97,108,108,97,64,108,111,99,97,108,104,111,115,116>> — имя ноды: <<"valhalla@localhost">>, 18 байтов
- <<0,0,0,15>> — идентификатор в таблице процессов ноды (ID), значащие только 15 бит, остальные заполняются нулями
- <<0,0,0,0>> — продолжение предыдущего поля (serial), на случай, когда процессов так много, что 15 бит не хватило
- 3 — Один байт, содержащий счётчик (creation); значения 1..3 (в будущем диапазон может быть изменён)
- 100 — метка типа терма, атома, содержащего в себе имя ноды, на которой находится процесс
Счётчик creation инкрементируется при каждом перезапуске ноды с этим именем. В нашем случае видно, что нода valhalla@localhost была запущена три раза. Получить его можно, вызвав erlang:system_info(creation).
Счётчик хранится на EPMD — Erlang Port Mapper Daemon. Это сервис, отвечающий за взаимодействие между нодами в кластере. При старте ноды, она сообщает EPMD порт, в который должны приходить сообщения от других нод (удалённые ноды после определения адреса хоста по имени нужной ноды соединяются с epmd, узнают у него порт конкретной ноды на этом хосте и взаимодействуют с ней уже напрямую). EPMD в свою очередь возвращает ноде значение creation. При первом запуске ноды ей будет назначено случайное значение счётчика.
Наверное, все уже поняли, для чего этот счётчик существует. Да, тот самый let it crash. Если на ноде случается самая непредвиденная ошибка, и ничего нельзя сделать, кроме как перезапустить всю ноду целиком (ну или она сама грохнулась), специальная служба heart её перезапустит, нода получит новое значение creation. Это в некоторой мере позволяет различить идентификаторы от разных инкарнаций нод (но лучше всё же использовать erlang:monitor/2).
Итак, прозрачность идентификаторов процессов обеспечивается тем, что идентификатор содержит в себе полную информацию, имея которую, можно легко вычислить его координаты на кластере.
Tweet
metachord
Comments
Andrey Pampukha
Posted 1 year ago.
Спасибо за интересную статью!
Ещё есть функция erlang:node/1, которая волшебным образом выцепляет имя ноды из пида :-)
8> node(self()).
nonode@nohost
Развлечения ради можно и свою реализовать:
28> F=fun(Pid)->B=term_to_binary(Pid), list_to_atom(binary_to_list(binary:part(B, 5, binary:at(B,4)))) end.
#Fun<erl_eval.6.13229925>
29> F(self()).
nonode@nohost
IAD
Posted 11 months, 27 days ago.
Пиши исчо
Leave a comment