ua-hosting.company
Компания
170,40
рейтинг
20 января в 14:51

Разработка → Минимальный HTTP API Endpoint используя Elixir

Давайте рассмотрим создание минимального HTTP API Endpoint используя Elixir. Так же, как и Rack в Ruby, Elixir идет в комплекте с Plug. Это универсальный инструмент для работы с HTTP соединениями.



Использование Plug: строим Endpoint HTTP

Во-первых, давайте создадим новый проект Elixir:

$ mix new http_api --sup


Новое Elixir OTP приложение создано. Теперь нужно добавить :cowboy и :plug в виде шестнадцатиричных и примененных зависимостей.

# Измените следующие части в <code>mix.exs</code>

  def application do
    [applications: [:logger, :cowboy, :plug],
     mod: {HttpApi, []}]
  end

  defp deps do
    [
      {:cowboy, "~>1.0.4"},
      {:plug, "~>1.1.0"}
    ]
  end


Plug комплектуется маршрутизатором, который мы можем использовать для простого создания Endpoint HTTP. Давайте создадим модуль, чтобы инкапсулировать маршрутизатор:

# lib/http_api/router.ex
defmodule HttpApi.Router do
  use Plug.Router

  plug :match
  plug :dispatch

  get "/" do
    send_resp(conn, 200, "Hello Plug!")
  end

  match _ do
    send_resp(conn, 404, "Nothing here")
  end
end


Если Вы работали с фреймворками, подобными sinatra, все это покажется Вам знакомым. Можете изучить документацию по маршрутизатору, если Вам любопытно узнать, как это все работает.

Для запуска сервера нужно, чтобы супервизор данного приложения запустил Plug Cowboy адаптер

# lib/http_api.ex

defmodule HttpApi do
  use Application

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      # `start_server` function is used to spawn the worker process
      worker(__MODULE__, [], function: :start_server)
    ]
    opts = [strategy: :one_for_one, name: HttpApi.Supervisor]
    Supervisor.start_link(children, opts)
  end

  # Start Cowboy server and use our router
  def start_server do
    { :ok, _ } = Plug.Adapters.Cowboy.http HttpApi.Router, []
  end
end


Полный код для приведенного выше примера можно найти здесь. Вы можете запустить сервер с помощью:

$ iex -S mix


Команда запускает интерактивную оболочку Elixir, а также и Ваше приложение на Erlang VM. Теперь можем перейти к более веселой части.

Визуализация использования процессов: observer


В подсказке iex запустите Erlang :observer инструмент, используя эту команду:

iex> :observer.start

Команда открывает GUI интерфейс, который выглядит примерно так:



На левой стороне панели Applications Вы видите список всех приложений, в настоящее время работающих на Erlang VM — это включает наше приложение (http_api) и все его зависимости. Важными для нас являются Cowboy и Ranch.

Cowboy и Ranch


Cowboy — популярный HTTP сервер в мире Erlang. И он использует Ranch — библиотеку Erlang для обработки TCP соединений.
Когда мы запускаем маршрутизатор Plug, то переходим на модуль маршрутизатора для Plug’s Cowboy адаптера. Получая соединение, Cowboy передает его к Plug, а тот, в свою очередь, обрабатывает соединение и посылает запрос обратно.

Параллельные запросы


Plug по умолчанию просит, чтобы Cowboy запустил 100 TCP принимающих соединений Ranch. Вы можете видеть 100 принимающих процессов для себя, если видите график использования приложения в Ranch используя :observer.



Означает ли это, что может быть только 100 параллельных соединений? Давайте узнаем. Мы изменим число получателей к 2, передавая его в качестве параметра для адаптера Plug’s Cowboy:

Plug.Adapters.Cowboy.http HttpApi.Router, [], [acceptors: 2]


Давайте посмотрим, как процессы выглядят теперь:



Хорошо, таким образом у нас есть только 2 принимающих процесса соединения TCP. Давайте попытаемся выполнить 5 длительных параллельных запросов и посмотреть, что из этого получится.

# lib/http_api/router.ex

# Modify router to add some sleep
defmodule HttpApi.Router do
  use Plug.Router

  plug :match
  plug :dispatch

  # Sleep for 100 seconds before sending the reponse
  get "/" do
    :timer.sleep(100000)
    send_resp(conn, 200, "Hello Plug!")
  end

  match _ do
    send_resp(conn, 404, "Nothing here")
  end
end


Теперь давайте выполним 5 запросов, делая это в подсказке iex:

for n <- 1..5, do: spawn(fn -> :httpc.request('http://localhost:4000') end)


Запустите :observer от использования iex :observer.start и посмотрите график процесса:



Мы видим, что все еще есть только 2 принимающих процесса, а 5 других были порождены где-то в другом месте. Это процессы соединения, которые содержат принятые соединения. Что значит — принимающие процессы не диктуют, сколько процессов мы можем принимать за один раз. Нет, они просто ограничивают новые процессов, которые могут быть приняты за один раз. Даже если Вы хотите обслуживать 1000 параллельных запросов, безопасно оставить число принимающих процессов в значении по умолчанию 100.

Итог


Вы можете создать простые конечные точки HTTP, используя Plug маршрутизатор.
Ranch способен обработать многократные соединения TCP за один раз, создавая процессы.
Erlang :observer — отличный способ визуализировать параллелизм в Ваших приложениях.
Получатель обрабатывает только принятые соединения. Из них Вам нужны лишь 100.

APD: Оригинал данного поста доступен тут.
Автор: @habit
ua-hosting.company
рейтинг 170,40
Компания прекратила активность на сайте

Комментарии (5)

  • +2
    Эээ, а ничего, что это (посредственный) перевод статьи совсем другого человека?
    • +1
      Приветствую.

      Это перевод поста написанного мистером Emil Soman. Я действительно забыл дать ссылку на первоисточник, увы, но все мы люди. Спасибо, что деликатно про это напомнили.
      • +4
        «шестнадцатиричные зависимости» убили намертво. вы с Elixir знакомы вообще хоть немного?
        • +3
          hex and application dependencies

          Да тут машинный перевод.
          • +3
            Да и в фразе «Ranch способен обработать многократные соединения TCP за один раз, создавая процессы.» мне кажется, имеется ввиду «множество».

            «Теперь давайте выполним 5 запросов, делая это в подсказке iex:»
            В командной строке видимо?

            Вообще весь текст будто переводился человеком «не в теме». Обычно рекомендуется подобные вещи отправлять в личку, но думаю, для такой короткой заметки ошибок чересчур.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка