Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Отличие Erlang от объектных языков

4,251 views

Published on

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

Published in: Technology, News & Politics
  • Be the first to comment

Отличие Erlang от объектных языков

  1. 1. Erlang Макс Лапшин max@evilmartians.com http://erlyvideo.org/
  2. 2. Erlang
  3. 3. Erlang Был разработан в Ericsson инженерами, которым хотелось больше спать по ночам и не работать в выходные
  4. 4. Область применения • Сетевые сервисы
  5. 5. Область применения • Сетевые сервисы с постоянно подключенными клиентами
  6. 6. Что заменяет? • С++ • Java • Ruby • Perl
  7. 7. Что заменяет? • С++ • Java • Ruby • Perl • зоопарк из кучи программ, собранных на соплях шелл-скриптов и monit-а сбоку
  8. 8. ООП • Инкапсуляция • Наследование • Полиморфизм. Который на самом деле мономорфизм.
  9. 9. ООП • Инкапсуляция • Наследование • Полиморфизм. Который на самом деле мономорфизм. • Обработка ошибок • Распределенная работа
  10. 10. Цикл жизни объекта • Создание • Обработка метода • Смена состояния • п. 2 • Уничтожение
  11. 11. Erlang-овские процессы array(Data) -> NewData = perform_action(Data), array(NewData).
  12. 12. Классический вызов метода result = object.method(arg1, arg2);
  13. 13. Вызов — посылка сообщения Array ! {set, Index, Value}.
  14. 14. Прием метода эксплицитный array(Data) -> receive {set, Index, Value} -> array(set(Data,Index,Value)) end.
  15. 15. gen_server:call иммитация вызова метода gen_server:call(Array, {get, 3}).
  16. 16. Внутри вызывающего: Ref = make_ref(), Array ! {‘call’,self(),Ref,{get,4}}.
  17. 17. Внутри объекта: receive {‘call’,Pid,Ref,Call} -> Pid ! {Ref,handle(Call,State)}
  18. 18. Отложенный ответ receive {‘call’,Pid,Ref,Call} -> Result = handle(Call,State, ... Pid ! {Ref, Result}
  19. 19. «Объекты» • Вместо объектов процессы • Вместо ссылок — pid-ы • Вместо вызовов методов — посылка сообщений • «Методы» накапливаются — мейлбокс процесса
  20. 20. Синхронизация доступа к объектам array.set(array.length, value);
  21. 21. Синхронизация доступа к объектам mutex.lock(); array.set(array.length, value); mutex.unlock();
  22. 22. Синхронизация в Erlang • Вызовы методов синхронизированы в мейлбоксе процесса • Процессы нереентерабельны by-design
  23. 23. Инкапсуляция • Во всех классических языках можно добраться до переменной внутри объекта
  24. 24. Инкапсуляция • В Erlang процессы общаются только сообщениями • Данные и ошибки изолированы внутри процессов
  25. 25. Инкапсуляция • В Erlang процессы общаются только сообщениями • Данные и ошибки изолированы внутри процессов почти всегда: есть ets, dets и IO
  26. 26. Наследование • В erlang наследования нет • Есть композиция: gen_server, gen_fsm
  27. 27. Behaviour gen_server receive {‘call’, From, Call} -> Reply = M:handle_call(Call,State), reply(From,Reply); Else -> Module:handle_info(Else,State)
  28. 28. Behaviour gen_server gen_server.erl: start(Module, Args) -> State = Module:init(Args) our_module.erl: init(Args) -> ... handle_call(Call,State) -> ...
  29. 29. Полиморфизм • Процессы не имеют типов • Вся типизация duck-typing: процесс может отвечать на сообщение • По PID-у ничего про процесс не узнать (можно, но не стоит)
  30. 30. Обработка ошибок • Как локализовать ошибку? • Что делать, поймав её? • Как и кого наказать за ошибку?
  31. 31. Изоляция ошибок • Exceptions и ошибки живут только внутри процесса • Никаких проездов по стеку • valgrind можно убрать на полку
  32. 32. Let it crash • Стандартная практика — не обрабатывать ошибку {ok, File} = file:open(FileName, [read]) • Полагаться на каскадное завершение группы процессов
  33. 33. Время жизни объекта • GC коварен и недетерминирован • C++ и ObjectiveC дают контроль, но текут • Финализаторы образуют циклы и текут
  34. 34. Процесс завершается явно hash(Data) -> receive {set, Key, Value} -> hash(set(Key,Value,Data)); stop -> ok end.
  35. 35. Линки и мониторы • Один процесс получает сообщение о смерти другого erlang:monitor(process,Pid)
  36. 36. Монитор • реентерабелен • отменяется receive {‘DOWN’,Ref,process,Pid,Reason}
  37. 37. Ручной счетчик ссылок • Объект Client регистрируется у Server • при смерти Client, Server вычеркивает его из списка • после ухода последнего Client, Server сам решает как быть • кто ещё умеет удаляться с таймаутом?
  38. 38. Супервизоры • Специальные процессы, следящие за другими • Группы супервизоров объединяются в приложения • appmon:start()
  39. 39. RPC • Sun RPC • Corba • SOAP • и прочие ночные кошмары
  40. 40. Классические проблемы • Вызов удаленных методов • Передача сложных объектов • Распределенная сборка мусора • Обработка потери связности
  41. 41. RPC со встроенным Erlangом Array ! {append, Value}.
  42. 42. Прозрачная сеть • Посылка сообщений по сети прозрачна • Включая анонимные функции! Remote ! fun(S) -> S + 5 end; • Включая открытые файлы • И прочее-прочее
  43. 43. Мониторы по сети • Работают как обычные • К ним добавляется отдельный мониторинг нод
  44. 44. Глобальные переменные • Локальные erlang:register(rtmp_listener, Pid) rtmp_listener ! accept • Удаленные {‘ems@streamer2’,rtmp_listener} ! accept
  45. 45. Продакшн • Производительность • Слежение за ошибками • Перезапуск сбойных сервисов • Выкатывание обновлений
  46. 46. 10K+ пользователей • 10K пользователей нитками не обслужить • Нитки — минимум 2МБ памяти, фрагментированный стек • Нитки дорого • Есть epoll/kqueue
  47. 47. Evented • не надо писать код синхронизаций • epoll + threads — адское сочетание
  48. 48. erl -smp enable • Все данные в erlang немутабельны • Процесс легко мигрирует на другое ядро • Каждое ядро имеет свой шедулер • Линейное масштабирование по ядрам
  49. 49. Горячий апдейт кода • Классически решается рестартом сервера
  50. 50. В erlang апдейт из коробки • В момент tail call начинает выполняться новый код • Код приложения заливается по сети на другие ноды
  51. 51. Резюме • Решена проблема синхронизации доступа к объектам • Эффективно скрещен epoll/kqueue с нитками • 100% изоляция данных и ошибок в объектах • Работающий горячий апдейт кода • Простой как валенок и работающий штатный RPC
  52. 52. Вопросы? Макс Лапшин max@maxidoors.ru http://levgem.livejournal.com/

×