Elixir 1.7 - Distributed tasks and configuration

वितरित कार्य और कॉन्फ़िगरेशन




elixir

वितरित कार्य और कॉन्फ़िगरेशन

यह अध्याय मिक्स और ओटीपी गाइड का हिस्सा है और यह इस गाइड में पिछले अध्यायों पर निर्भर करता है। अधिक जानकारी के लिए, परिचय मार्गदर्शिका पढ़ें या साइडबार में अध्याय सूचकांक देखें।

इस अंतिम अध्याय में, हम वापस जाएंगे :kv एप्लिकेशन और एक राउटिंग लेयर जोड़ेंगे जो हमें बाल्टी नाम के आधार पर नोड्स के बीच अनुरोध वितरित करने की अनुमति देगा।

रूटिंग परत को निम्न प्रारूप की एक रूटिंग तालिका प्राप्त होगी:

[
  {?a..?m, :"[email protected]"},
  {?n..?z, :"[email protected]"}
]

राउटर टेबल के खिलाफ बकेट नाम के पहले बाइट की जांच करेगा और उसके आधार पर उपयुक्त नोड को भेजेगा। उदाहरण के लिए, "बाल्टी" ((पत्र के यूनिकोड कोड का प्रतिनिधित्व करता है) पत्र के साथ शुरू होने वाली एक बाल्टी को नोड [email protected] नोड भेजा जाएगा।

यदि मिलान प्रविष्टि नोड को अनुरोध का मूल्यांकन करने के लिए इंगित करती है, तो हमने रूटिंग समाप्त कर दी है, और यह नोड अनुरोध किए गए ऑपरेशन को निष्पादित करेगा। यदि मिलान प्रविष्टि एक अलग नोड की ओर इशारा करती है, तो हम इस नोड के लिए अनुरोध पारित करेंगे, जो अपनी स्वयं की रूटिंग टेबल को देखेगा (जो कि पहले नोड से भिन्न हो सकती है) और तदनुसार कार्य करेगा। यदि कोई प्रविष्टि मेल नहीं खाती है, तो एक त्रुटि उठाई जाएगी।

आप आश्चर्यचकित हो सकते हैं कि हम अपनी रूटिंग तालिका में पाए गए नोड को सीधे अनुरोधित ऑपरेशन करने के लिए क्यों नहीं कहते हैं, लेकिन इसके बजाय उस नोड पर प्रक्रिया करने के लिए राउटिंग अनुरोध पास करें। जबकि एक रूटिंग टेबल जितनी सरल है, उतनी ही ऊपर सभी नोड्स के बीच साझा की जा सकती है, इस तरह से राउटिंग अनुरोध पर पास होने से राउटिंग टेबल को छोटे टुकड़ों में तोड़ना बहुत आसान हो जाता है क्योंकि हमारा आवेदन बढ़ता है। शायद कुछ बिंदु पर, [email protected] केवल बाल्टी अनुरोधों को रूट करने के लिए ज़िम्मेदार होगा, और इसे संभालती हुई बाल्टी को विभिन्न नोड्स में भेजा जाएगा। इस तरह, [email protected] को इस परिवर्तन के बारे में कुछ भी जानने की आवश्यकता नहीं है।

नोट: हम इस अध्याय में एक ही मशीन में दो नोड्स का उपयोग करेंगे। आप एक ही नेटवर्क पर दो (या अधिक) विभिन्न मशीनों का उपयोग करने के लिए स्वतंत्र हैं, लेकिन आपको कुछ प्रस्तुत करने का काम करने की आवश्यकता है। सबसे पहले, आपको यह सुनिश्चित करने की आवश्यकता है कि सभी मशीनों में एक ही मूल्य के साथ एक ~/.erlang.cookie फ़ाइल है। दूसरा, आपको यह गारंटी epmd आवश्यकता है कि epmd एक बंदरगाह पर चल रहा है जो अवरुद्ध नहीं है (आप डिबग जानकारी के लिए epmd -d चला सकते हैं)। तीसरा, यदि आप सामान्य रूप से वितरण के बारे में अधिक जानना चाहते हैं, तो हम लर्न यू एअर एलांग से इस महान डिस्ट्रिब्यूनिकॉन अध्याय की सिफारिश करते हैं

हमारा पहला वितरित कोड

अमृत ​​के साथ जहाजों को जोड़ने और उनके बीच सूचनाओं के आदान-प्रदान की सुविधा है। वास्तव में, हम वितरित वातावरण में काम करने के दौरान प्रक्रियाओं की एक ही अवधारणा का उपयोग करते हैं, संदेश पास करते हैं और संदेश प्राप्त करते हैं क्योंकि अमृत प्रक्रियाएं स्थान पारदर्शी हैं । इसका मतलब यह है कि संदेश भेजते समय, यह मायने नहीं रखता कि प्राप्तकर्ता प्रक्रिया एक ही नोड पर है या किसी अन्य नोड पर, VM दोनों मामलों में संदेश देने में सक्षम होगा।

वितरित कोड को चलाने के लिए, हमें एक नाम के साथ वीएम शुरू करना होगा। नाम छोटा हो सकता है (जब एक ही नेटवर्क में) या लंबे समय तक (पूर्ण कंप्यूटर पते की आवश्यकता होती है)। आइए एक नया IEx सत्र शुरू करें:

$ iex --sname foo

आप देख सकते हैं कि अब संकेत थोड़ा अलग है और कंप्यूटर के नाम के बाद नोड नाम दिखाता है:

Interactive Elixir - press Ctrl+C to exit (type h() ENTER for help)
iex([email protected])1>

मेरे कंप्यूटर का नाम jv , इसलिए मैं उपरोक्त उदाहरण में [email protected] देखता हूं, लेकिन आपको एक अलग परिणाम मिलेगा। हम निम्नलिखित उदाहरणों में [email protected] उपयोग करेंगे और कोड को आज़माते समय आपको उनके अनुसार अपडेट करना चाहिए।

आइए इस शेल में Hello नाम के एक मॉड्यूल को परिभाषित करें:

iex> defmodule Hello do
...>   def world, do: IO.puts "hello world"
...> end

यदि आपके पास Erlang और Elixir दोनों के समान नेटवर्क पर एक और कंप्यूटर है, तो आप उस पर एक और शेल शुरू कर सकते हैं। यदि आप नहीं करते हैं, तो आप दूसरे टर्मिनल में IEx सत्र शुरू कर सकते हैं। या तो मामले में, इसे संक्षिप्त नाम दें:

$ iex --sname bar

ध्यान दें कि इस नए IEx सत्र के अंदर, हम Hello.world/0 उपयोग नहीं कर सकते हैं:

iex> Hello.world
** (UndefinedFunctionError) undefined function: Hello.world/0
    Hello.world()

हालाँकि, हम [email protected] से [email protected] पर एक नई प्रक्रिया शुरू कर सकते हैं! आइए इसे आजमाएँ (जहाँ @computer-name वह है जिसे आप स्थानीय रूप से देखते हैं):

iex> Node.spawn_link :"[email protected]", fn -> Hello.world end
#PID<9014.59.0>
hello world

अमृत ​​ने एक और नोड पर एक प्रक्रिया शुरू की और अपने पीआईडी ​​को वापस कर दिया। कोड तब दूसरे नोड पर निष्पादित किया जाता है जहां Hello.world/0 फ़ंक्शन मौजूद है और उस फ़ंक्शन को लागू किया है। ध्यान दें कि "हैलो वर्ल्ड" का परिणाम वर्तमान नोड bar पर मुद्रित किया गया था, न कि foo पर। दूसरे शब्दों में, मुद्रित किए जाने वाले संदेश को foo से bar वापस भेज दिया गया था। ऐसा इसलिए होता है क्योंकि अन्य नोड ( foo ) पर प्रक्रिया शुरू होने के बाद भी वर्तमान नोड ( bar ) का समूह नेता होता है। हमने आईओ अध्याय में समूह के नेताओं के बारे में संक्षेप में बात की है।

हम हमेशा की तरह Node.spawn_link/2 द्वारा लौटाए गए pid से संदेश भेज और प्राप्त कर सकते हैं। आइए एक त्वरित पिंग-पोंग उदाहरण का प्रयास करें:

iex> pid = Node.spawn_link :"[email protected]", fn ->
...>   receive do
...>     {:ping, client} -> send client, :pong
...>   end
...> end
#PID<9014.59.0>
iex> send pid, {:ping, self()}
{:ping, #PID<0.73.0>}
iex> flush()
:pong
:ok

हमारी त्वरित खोज से, हम यह निष्कर्ष निकाल सकते हैं कि हमें वितरित गणना करने के लिए हर बार दूरस्थ नोड पर प्रक्रियाओं को Node.spawn_link/2 लिए Node.spawn_link/2 का उपयोग करना चाहिए। हालांकि, हमने इस गाइड में सीखा है कि पर्यवेक्षण पेड़ों के बाहर स्पॉनिंग प्रक्रियाओं को यदि संभव हो तो टाला जाना चाहिए, इसलिए हमें अन्य विकल्पों की तलाश करने की आवश्यकता है।

Node.spawn_link/2 तीन बेहतर विकल्प हैं जिन्हें हम अपने कार्यान्वयन में उपयोग कर सकते हैं:

  1. हम दूरस्थ नोड पर फ़ंक्शंस निष्पादित करने के लिए Erlang :rpc मॉड्यूल का उपयोग कर सकते हैं। उपरोक्त [email protected] शेल के अंदर, आप कॉल कर सकते हैं :rpc.call(:"[email protected]", Hello, :world, []) और यह "हैलो वर्ल्ड" प्रिंट करेगा

  2. हमारे पास दूसरे नोड पर चलने वाला सर्वर हो सकता है और GenServer API के माध्यम से उस नोड के लिए अनुरोध भेज GenServer है। उदाहरण के लिए, आप GenServer.call({name, node}, arg) का उपयोग करके किसी दूरस्थ नोड पर किसी सर्वर को कॉल कर सकते हैं या दूरस्थ प्रक्रिया PID को पहले तर्क के रूप में पास कर सकते हैं।

  3. हम उन tasks उपयोग कर सकते हैं, जिनके बारे में हमने पिछले अध्याय में सीखा है, क्योंकि उन्हें स्थानीय और दूरस्थ दोनों नोड्स पर लिखा जा सकता है

उपरोक्त विकल्पों में विभिन्न गुण हैं। दोनों :rpc rpc और एक GenServer का उपयोग करके एक सर्वर पर आपके अनुरोधों को क्रमबद्ध किया जाएगा, जबकि कार्य प्रभावी रूप से दूरस्थ नोड पर अतुल्यकालिक रूप से चल रहे हैं, जिसमें केवल क्रमांकन बिंदु पर्यवेक्षक द्वारा किया गया स्पॉइंग है।

हमारी रूटिंग परत के लिए, हम कार्यों का उपयोग करने जा रहे हैं, लेकिन अन्य विकल्पों का भी पता लगाने के लिए स्वतंत्र महसूस करते हैं।

async / इंतजार

अब तक हमने ऐसे कार्यों की खोज की है जो उनके वापसी मूल्य के संबंध में नहीं होने के साथ, अलगाव में शुरू और चलाए जा रहे हैं। हालांकि, कभी-कभी एक मूल्य की गणना करने और बाद में इसके परिणाम को पढ़ने के लिए एक कार्य को चलाने के लिए उपयोगी होता है। इसके लिए, कार्य async/await पैटर्न भी प्रदान करते हैं:

task = Task.async(fn -> compute_something_expensive end)
res  = compute_something_else()
res + Task.await(task)

async/await समवर्ती रूप से मूल्यों की गणना करने के लिए एक बहुत ही सरल तंत्र प्रदान करता है। इतना ही नहीं, async/await Task.Supervisor का उपयोग उसी Task.Supervisor साथ भी किया जा सकता है। Task.Supervisor जिसका उपयोग हमने पिछले अध्यायों में किया है। हमें बस Task.Supervisor.async/2 जगह Task.Supervisor.async/2 को कॉल करने की जरूरत है। बाद में परिणाम पढ़ने के लिए Task.Supervisor.start_child/2 और Task.Supervisor.start_child/2 का उपयोग करें।

वितरित कार्य

वितरित कार्य बिल्कुल वैसे ही हैं जैसे कि पर्यवेक्षित कार्य। एकमात्र अंतर यह है कि हम पर्यवेक्षक पर कार्य को स्पॉइन करते समय नोड नाम पास करते हैं। :kv एप्लिकेशन से lib/kv/supervisor.ex . lib/kv/supervisor.ex खोलें। आइए पेड़ के अंतिम बच्चे के रूप में एक कार्य पर्यवेक्षक जोड़ें:

{Task.Supervisor, name: KV.RouterTasks},

अब, फिर से दो नामित नोड्स शुरू करते हैं, लेकिन अंदर :kv एप्लिकेशन:

$ iex --sname foo -S mix
$ iex --sname bar -S mix

अंदर [email protected] , अब हम सुपरवाइजर के माध्यम से दूसरे नोड पर सीधे एक कार्य कर सकते हैं:

iex> task = Task.Supervisor.async {KV.RouterTasks, :"[email protected]"}, fn ->
...>   {:ok, node()}
...> end
%Task{owner: #PID<0.122.0>, pid: #PID<12467.88.0>, ref: #Reference<0.0.0.400>}
iex> Task.await(task)
{:ok, :"[email protected]"}

हमारा पहला वितरित कार्य उस नोड के नाम को पुनः प्राप्त करता है जो कार्य चल रहा है। सूचना हमने Task.Supervisor.async/2 लिए एक अनाम फ़ंक्शन दिया है। Task.Supervisor.async/2 लेकिन, वितरित मामलों में, मॉड्यूल, फ़ंक्शन और तर्कों को स्पष्ट रूप से देना बेहतर है:

iex> task = Task.Supervisor.async {KV.RouterTasks, :"[email protected]"}, Kernel, :node, []
%Task{owner: #PID<0.122.0>, pid: #PID<12467.89.0>, ref: #Reference<0.0.0.404>}
iex> Task.await(task)
:"[email protected]"

अंतर यह है कि अनाम फ़ंक्शन को कॉल नोड के समान लक्ष्य संस्करण की आवश्यकता होती है। मॉड्यूल, फ़ंक्शन और तर्कों का उपयोग करना अधिक मजबूत है, क्योंकि आपको केवल दिए गए मॉड्यूल में मिलान एरिटी के साथ फ़ंक्शन खोजने की आवश्यकता है।

हाथ में इस ज्ञान के साथ, चलो अंत में रूटिंग कोड लिखें।

रूटिंग लेयर

निम्नलिखित सामग्री के साथ lib/kv/router.ex पर एक फ़ाइल बनाएँ:

defmodule KV.Router do
  @doc """
  Dispatch the given `mod`, `fun`, `args` request
  to the appropriate node based on the `bucket`.
  """
  def route(bucket, mod, fun, args) do
    # Get the first byte of the binary
    first = :binary.first(bucket)

    # Try to find an entry in the table() or raise
    entry =
      Enum.find(table(), fn {enum, _node} ->
        first in enum
      end) || no_entry_error(bucket)

    # If the entry node is the current node
    if elem(entry, 1) == node() do
      apply(mod, fun, args)
    else
      {KV.RouterTasks, elem(entry, 1)}
      |> Task.Supervisor.async(KV.Router, :route, [bucket, mod, fun, args])
      |> Task.await()
    end
  end

  defp no_entry_error(bucket) do
    raise "could not find entry for #{inspect bucket} in table #{inspect table()}"
  end

  @doc """
  The routing table.
  """
  def table do
    # Replace computer-name with your local machine name.
    [{?a..?m, :"[email protected]"}, {?n..?z, :"[email protected]"}]
  end
end

हमारे राउटर कार्यों को सत्यापित करने के लिए एक परीक्षण लिखें। test/kv/router_test.exs नामक एक फ़ाइल बनाएँ:

defmodule KV.RouterTest do
  use ExUnit.Case, async: true

  test "route requests across nodes" do
    assert KV.Router.route("hello", Kernel, :node, []) ==
           :"[email protected]"
    assert KV.Router.route("world", Kernel, :node, []) ==
           :"[email protected]"
  end

  test "raises on unknown entries" do
    assert_raise RuntimeError, ~r/could not find entry/, fn ->
      KV.Router.route(<<0>>, Kernel, :node, [])
    end
  end
end

पहला परीक्षण Kernel.node/0 आमंत्रित करता है, जो बाल्टी नाम "हैलो" और "दुनिया" के आधार पर, वर्तमान नोड का नाम देता है। अब तक की हमारी रूटिंग टेबल के अनुसार, हमें क्रमशः प्रतिक्रियाओं के रूप में [email protected] और [email protected] मिलना चाहिए।

दूसरा परीक्षण जांचता है कि कोड अज्ञात प्रविष्टियों के लिए उठाता है।

पहला परीक्षण चलाने के लिए, हमें दो नोड्स चलाने होंगे। apps/kv में ले जाएं और bar नाम के नोड को रीस्टार्ट करें जो कि परीक्षणों द्वारा उपयोग किया जा रहा है।

$ iex --sname bar -S mix

और अब इसके साथ परीक्षण चलाएं:

$ elixir --sname foo -S mix test

परीक्षा पास करनी चाहिए।

परीक्षण फ़िल्टर और टैग

यद्यपि हमारे परीक्षण पास होते हैं, हमारी परीक्षण संरचना अधिक जटिल होती जा रही है। विशेष रूप से, केवल mix test साथ रनिंग टेस्ट हमारे सूट में विफलताओं का कारण बनता है, क्योंकि हमारे टेस्ट को दूसरे नोड के लिए कनेक्शन की आवश्यकता होती है।

सौभाग्य से, परीक्षण टैग करने के लिए एक सुविधा के साथ जहाजों का उपयोग करें, हमें उन टैगों के आधार पर विशिष्ट कॉलबैक या यहां तक ​​कि फिल्टर परीक्षण चलाने की अनुमति देता है। हमने पहले से ही उपयोग किया है :capture_log पिछले अध्याय में :capture_log टैग, जिसमें इसके शब्दार्थ खुद एक्सयूनाइट द्वारा निर्दिष्ट हैं।

इस बार आइए, एक जोड़ :distributed टैग को test/kv/router_test.exs :

@tag :distributed
test "route requests across nodes" do

@tag :distributed लिखना @tag :distributed @tag distributed: true करने के बराबर है @tag distributed: true

ठीक से टैग किए गए परीक्षण के साथ, हम अब जांच सकते हैं कि नोड नेटवर्क पर जीवित है या नहीं, यदि नहीं, तो हम सभी वितरित परीक्षणों को बाहर कर सकते हैं। test/test_helper.exs अंदर test/test_helper.exs खोलें :kv और निम्नलिखित जोड़ें:

exclude =
  if Node.alive?, do: [], else: [distributed: true]

ExUnit.start(exclude: exclude)

अब mix test साथ mix test चलाएं:

$ mix test
Excluding tags: [distributed: true]

.......

Finished in 0.1 seconds (0.1s on load, 0.01s on tests)
7 tests, 0 failures, 1 skipped

इस बार सभी परीक्षण पास हो गए और ExUnit ने हमें चेतावनी दी कि वितरित परीक्षणों को बाहर रखा जा रहा है। यदि आप $ elixir --sname foo -S mix test परीक्षण के साथ परीक्षण चलाते हैं, तो एक अतिरिक्त परीक्षण चलाना चाहिए और जब तक [email protected] नोड उपलब्ध है तब तक सफलतापूर्वक पास।

mix test कमांड हमें टैग को गतिशील रूप से शामिल करने और बाहर करने की भी अनुमति देता है। उदाहरण के लिए, हम test/test_helper.exs में निर्धारित मूल्य की परवाह किए बिना वितरित परीक्षण चलाने के लिए $ mix test --include distributed test/test_helper.exs । हम कमांड लाइन से किसी विशेष टैग को बाहर करने के लिए भी पास कर सकते हैं। अंत में, - केवल एक विशेष टैग के साथ परीक्षण चलाने के लिए इस्तेमाल किया जा सकता है:

$ elixir --sname foo -S mix test --only distributed

आप ExUnit.Case मॉड्यूल प्रलेखन में फ़िल्टर, टैग और डिफ़ॉल्ट टैग के बारे में अधिक पढ़ सकते हैं।

अनुप्रयोग वातावरण और कॉन्फ़िगरेशन

अब तक हमने KV.Router मॉड्यूल में रूटिंग टेबल को हार्डकोड किया है। हालाँकि, हम तालिका को गतिशील बनाना चाहते हैं। यह हमें न केवल विकास / परीक्षण / उत्पादन को कॉन्फ़िगर करने की अनुमति देता है, बल्कि विभिन्न नोड्स को राउटिंग टेबल में विभिन्न प्रविष्टियों के साथ चलने की अनुमति भी देता है। ओटीपी की एक विशेषता है जो बिल्कुल वैसा ही करती है: अनुप्रयोग वातावरण।

प्रत्येक एप्लिकेशन में एक वातावरण होता है जो कुंजी द्वारा एप्लिकेशन के विशिष्ट कॉन्फ़िगरेशन को संग्रहीत करता है। उदाहरण के लिए, हम रूटिंग टेबल को :kv एप्लिकेशन वातावरण में संग्रहीत कर सकते हैं, इसे एक डिफ़ॉल्ट मान दे सकते हैं और अन्य अनुप्रयोगों को आवश्यकतानुसार तालिका को बदलने की अनुमति दे सकते हैं।

apps/kv/mix.exs और निम्नलिखित को वापस करने के लिए application/0 फ़ंक्शन को बदलें:

def application do
  [
    extra_applications: [:logger],
    env: [routing_table: []],
    mod: {KV, []}
  ]
end

हमने एप्लिकेशन में एक नई :env कुंजी जोड़ी है। यह एप्लिकेशन डिफ़ॉल्ट वातावरण लौटाता है, जिसमें कुंजी की प्रविष्टि होती है :routing_table और रिक्त सूची का मान। यह अनुप्रयोग वातावरण के लिए एक खाली तालिका के साथ जहाज करने के लिए समझ में आता है, क्योंकि विशिष्ट रूटिंग टेबल परीक्षण / परिनियोजन संरचना पर निर्भर करता है।

हमारे कोड में एप्लिकेशन वातावरण का उपयोग करने के लिए, हमें नीचे परिभाषा के साथ KV.Router.table/0 को बदलने की आवश्यकता है:

@doc """
The routing table.
"""
def table do
  Application.fetch_env!(:kv, :routing_table)
end

हम Application.fetch_env!/2 उपयोग करते हैं: Application.fetch_env!/2 लिए प्रविष्टि पढ़ने के लिए :routing_table in :kv का वातावरण। एप्लिकेशन मॉड्यूल में एप्लिकेशन वातावरण में हेरफेर करने के लिए आप अधिक जानकारी और अन्य फ़ंक्शन पा सकते हैं।

चूंकि हमारी राउटिंग टेबल अब खाली है, इसलिए हमारी वितरित परीक्षा विफल होनी चाहिए। विफलता को देखने के लिए ऐप्स को पुनरारंभ करें और परीक्षण फिर से चलाएं:

$ iex --sname bar -S mix
$ elixir --sname foo -S mix test --only distributed

एप्लिकेशन वातावरण के बारे में दिलचस्प बात यह है कि इसे न केवल वर्तमान एप्लिकेशन के लिए, बल्कि सभी अनुप्रयोगों के लिए कॉन्फ़िगर किया जा सकता है। ऐसा विन्यास config/config.exs फ़ाइल द्वारा किया जाता है। उदाहरण के लिए, हम IEx डिफ़ॉल्ट प्रॉम्प्ट को दूसरे मान में कॉन्फ़िगर कर सकते हैं। बस apps/kv/config/config.exs खोलें apps/kv/config/config.exs और अंत में निम्नलिखित जोड़ें:

config :iex, default_prompt: ">>>"

IEx की शुरुआत iex iex -S mix और आप देख सकते हैं कि IEx प्रॉम्प्ट बदल गया है।

इसका अर्थ है कि हम अपने :routing_table सीधे apps/kv/config/config.exs फ़ाइल में कॉन्फ़िगर कर सकते हैं:

# Replace computer-name with your local machine nodes.
config :kv, :routing_table, [{?a..?m, :"[email protected]"}, {?n..?z, :"[email protected]"}]

नोड्स को पुनरारंभ करें और वितरित परीक्षण फिर से चलाएं। अब वे सभी पास होना चाहिए।

Elixir v1.2 के बाद से, सभी छाता अनुप्रयोग अपने विन्यास साझा करते हैं, सभी बच्चों के कॉन्फ़िगरेशन को लोड करने वाले छाता रूट में config/config.exs में इस लाइन के लिए धन्यवाद:

import_config "../apps/*/config/config.exs"

mix run कमांड एक --config ध्वज को भी स्वीकार करता है, जो कॉन्फ़िगरेशन फ़ाइलों को मांग पर दिए जाने की अनुमति देता है। इसका उपयोग विभिन्न नोड्स को शुरू करने के लिए किया जा सकता है, प्रत्येक अपने स्वयं के विशिष्ट कॉन्फ़िगरेशन (उदाहरण के लिए, अलग-अलग रूटिंग टेबल) के साथ।

कुल मिलाकर, अनुप्रयोगों को कॉन्फ़िगर करने की अंतर्निहित क्षमता और इस तथ्य को कि हमने अपने सॉफ़्टवेयर को एक छतरी अनुप्रयोग के रूप में बनाया है, सॉफ़्टवेयर को तैनात करते समय हमें बहुत सारे विकल्प देता है। हम कर सकते हैं:

  • एक नोड के लिए छाता एप्लिकेशन को तैनात करें जो टीसीपी सर्वर और की-वैल्यू स्टोरेज दोनों के रूप में काम करेगा

  • परिनियोजित करें :kv_server एप्लिकेशन केवल टीसीपी सर्वर के रूप में काम करने के लिए जब तक कि राउटिंग टेबल केवल अन्य नोड्स पर इंगित करता है

  • केवल तभी लागू करें :kv एप्लिकेशन जब हम नोड को केवल संग्रहण के रूप में काम करना चाहते हैं (कोई टीसीपी एक्सेस नहीं)

जैसा कि हम भविष्य में और अधिक एप्लिकेशन जोड़ते हैं, हम अपनी तैनाती को उसी स्तर पर नियंत्रण के साथ जारी रख सकते हैं, चेरी-पिकिंग जिसमें कौन से एप्लिकेशन उत्पादन के लिए जा रहे हैं।

आप Distillery जैसे टूल के साथ कई रिलीज़ बनाने पर भी विचार कर सकते हैं, जो चुने गए एप्लिकेशन और कॉन्फ़िगरेशन को वर्तमान एर्लांग और एलिक्सिर इंस्टॉलेशन सहित पैकेज करेगा, इसलिए हम एप्लिकेशन को तब भी तैनात कर सकते हैं, जब रनटाइम लक्ष्य प्रणाली पर पूर्व-स्थापित नहीं है।

अंत में, हमने इस अध्याय में कुछ नई चीजें सीखी हैं, और उन्हें :kv_server एप्लिकेशन पर भी लागू किया जा सकता है। हम अगले कदमों को एक अभ्यास के रूप में छोड़ने जा रहे हैं:

  • 4040 के हार्डकोड किए गए मान का उपयोग करने के बजाय अपने अनुप्रयोग वातावरण से पोर्ट को पढ़ने के लिए :kv_server एप्लिकेशन को परिवर्तित करें

  • परिवर्तन और कॉन्फ़िगर करें :kv_server एप्लिकेशन को स्थानीय KV.Registry सीधे भेजने के बजाय रूटिंग कार्यक्षमता का उपयोग करने के लिए। के लिए :kv_server परीक्षण, आप राउटिंग टेबल पॉइंट को वर्तमान नोड में ही बना सकते हैं

उपसंहार

इस अध्याय में, हमने एलिक्सिर और एरलंग वीएम की वितरित सुविधाओं का पता लगाने के लिए एक सरल राउटर बनाया है, और सीखा है कि इसकी रूटिंग टेबल को कैसे कॉन्फ़िगर किया जाए। यह हमारे मिक्स और ओटीपी गाइड में अंतिम अध्याय है।

पूरे गाइड के दौरान, हमने जेनेरिक सर्वर, सुपरवाइज़र, टास्क, एजेंट, एप्लिकेशन और बहुत से निर्माणों का पता लगाने के लिए एक बहुत ही सरल वितरित कुंजी-मूल्य स्टोर बनाया है। इतना ही नहीं, हमने पूरे आवेदन के लिए परीक्षण लिखे हैं, एक्सयूनाइट से परिचित हैं, और सीखा है कि कार्यों की एक विस्तृत श्रृंखला को पूरा करने के लिए मिक्स बिल्ड टूल का उपयोग कैसे करें।

यदि आप उत्पादन में उपयोग करने के लिए वितरित की-वैल्यू स्टोर की तलाश कर रहे हैं, तो आपको निश्चित रूप से Riak ध्यान देना चाहिए, जो इरडांग वीएम में भी चलता है। रिआक में, बाल्टी को दोहराया जाता है, डेटा हानि से बचने के लिए, और एक राउटर के बजाय, वे एक बाल्टी को नोड पर मैप करने के लिए लगातार हैशिंग का उपयोग करते हैं। एक सुसंगत हैशिंग एल्गोरिथ्म उन डेटा की मात्रा को कम करने में मदद करता है जिन्हें माइग्रेट करने की आवश्यकता होती है जब बाल्टी को संग्रहीत करने के लिए नए नोड्स को आपके बुनियादी ढांचे में जोड़ा जाता है।

हैप्पी कोडिंग!