Как работят супервизорите в Elixir, Elixir Community и Phoenix Framework
В Erlang и Elixir надзорните органи са процеси, които управляват дъщерни процеси и ги рестартират, ако възникне грешка. Тази статия разглежда по-отблизо прилагащите надзорници в Elixir.
Но преди да преминете към самите супервизори, е добре да се запознаете с модулите gen_server и supervisor. Можете да се справите и без това, ако вече сте работили с еквивалентни модули Elixir, тъй като те просто предават повиквания към модулите Erlang, без да променят поведението си.
Нека започнем с пример от самата документация на Elixir:
В горния пример методът start_link създава супервизор, а методът init реализира обратното повикване, използвано от поведението от Supervisor. Нека разгледаме по-отблизо Supervisor.
Нека да разгледаме поведението. Операторът use Supervisor се разширява по време на компилиране в поведението, посочено в макроса __using__. Нека да разгледаме кода на макроса __using__ от модула Supervisor в източниците на Elixir .
По време на това писане макросът __using__ изглеждаше така:
@Behaviour проверява супервизора за необходимите функции за обратно извикване и операторът за импортиране зарежда допълнителни функции в MyApp.Supervisor от модула Supervisor.Spec. Тук са дефинирани функциите на работник и надзор. .
Накратко, инструкцията use Supervisor добавя няколко нови функции към проекта и следи за наличието на необходимите функции за обратно извикване.
Супервайзорът започва с извикване на MyApp.Supervisor.start_link. Той се делегира на функцията Supervisor.start_link чрез предаване на връзка към себе си (с помощта на макроса __MODULE__).
Нека да разгледаме внедряването на Supervisor.start_link:
Обърнете внимание, че модулът Elixir делегира повиквания към модула Erlang: supervisor. Но това не е причина за паника! Повярвайте ми и разгледайте източника на Erlang .
Търсейки start_link, ще срещнете оператор за експортиране, който ви позволява да използвате функция извън модула, спецификация, описваща типовете данни, налични за дадена функция, и всъщност самата им реализация:
Виждате ли? Вече нещо познато. Просто изпълняваме gen_server, без да навлизаме в подробности за това как работи. Основното нещо, което трябва да научите тук, е, че надзорните органи са изградени върху модула gen_server, който очаква да види многобройни обратни обаждания.
Методът init представлява много по-голям интерес. Имайте предвид, че въпреки че MyApp.Supervisor съдържа внедряването на функцията init, следващата функция няма да бъде извикана. Ако се върнете към изпълнението на функцията start_link в модула: supervisor от Erlang, ще забележите, че параметърът self е предаден към него. Това означава, че: supervisor.init е функцията, която търсите.
Погледнете изходния му код:
Първо се извиква функцията Mod: init (Args), която от своя страна извиква функцията MyApp.Supervisor.init. Нека да разгледаме още веднъж кода:
Не забравяйте, че работникът и надзорникът са помощници от Supervisor.Spec. Нека не бием около храста, а да преминем към най-важното, тоест, нека разгледаме по-отблизо как всичко това е приложено в Erlang. worker връща child_spec и контролира кортеж по следния начин:, child_specs >> .