伞应用初始化Elixir/Phoenix后写入文件,用于Heroku中的Nginx初始化

piztneat  于 2022-11-24  发布在  Phoenix
关注(0)|答案(1)|浏览(144)

我在Elixir中有一个伞式应用程序,它有两个应用程序端点,一个用于API,另一个用于IoT。我使用反向代理来服务应用程序,因为有两个端点在不同的端口上运行。
用于反向代理的生成包为:https://github.com/heroku/heroku-buildpack-nginx
这是我的Nginx配置文件。

daemon off;
worker_processes <%= ENV['NGINX_WORKERS'] || 4 %>;

events {
 use epoll;
 accept_mutex on;
 worker_connections <%= ENV['NGINX_WORKER_CONNECTIONS'] || 1024 %>;
}

http {
    gzip on;
    gzip_comp_level 2;
    gzip_min_length 512;

server_tokens off;

log_format l2met 'measure#nginx.service=$request_time request_id=$http_x_request_id';
access_log <%= ENV['NGINX_ACCESS_LOG_PATH'] || 'logs/nginx/access.log' %> l2met;
error_log <%= ENV['NGINX_ERROR_LOG_PATH'] || 'logs/nginx/error.log' %>;

include mime.types;
default_type application/octet-stream;
sendfile on;

#Must read the body in 5 seconds.
client_body_timeout 5;

upstream api {
    server 127.0.0.1:4000 max_fails=5 fail_timeout=60s;
}

upstream iot {
    server 127.0.0.1:4001 max_fails=5 fail_timeout=60s;
}

server {
    listen <%= ENV["PORT"] %>;
    server_name 0.0.0.0;
    keepalive_timeout 5;

    location /api {
        allow all;

        # Proxy Headers
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Cluster-Client-Ip $remote_addr;

        # The Important Websocket Bits!
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_pass http://api;

    }

    location /iot {
        allow all;

        # Proxy Headers
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-Cluster-Client-Ip $remote_addr;

        # The Important Websocket Bits!
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        proxy_pass http://iot;

    }
}

}
显然,一旦应用程序初始化,buildpack期望写入一个文件/tmp/app-initialized
我使用的命令是mix phx.server来启动保护伞。在Phoenix保护伞中的应用程序初始化后,写这个文件(/tmp/app-initialized)的正确方法是什么?

jtoj6r0c

jtoj6r0c1#

您可以看到phx.server任务phx.server.ex
您可以稍微修改一下,然后创建自己的任务来完成相同的任务,并编写文件:

defmodule Mix.Tasks.Bootstrap do
  use Mix.Task

  def run(_) do
    Application.put_env(:phoenix, :serve_endpoints, true, persistent: true)
    case Application.ensure_all_started(:the_name_of_your_app) do
       {:ok, _} ->
            ####
            #### write the file
            ####
            Mix.Tasks.Run.run run_args() ++ ["--no-start"]
       _error -> raise "Unable to start..."
    end
  end

  defp run_args do
    if iex_running?(), do: [], else: ["--no-halt"]
  end

  defp iex_running? do
    Code.ensure_loaded?(IEx) and IEx.started?
  end

end

您只需要将这个新文件放到lib中的某个位置,然后将命令作为mix bootstrap而不是mix phx.server传递。
考虑到应用程序和组件是如何在erlang和elixir中启动的,你也可以有一个简单的gen_server作为你的应用程序监督树的一部分,在端点被初始化之后,它会进行写操作。

defmodule Server.Application do

  @moduledoc false

  use Application

  def start(_type, _args) do
    children = [
      ServerWeb.Endpoint,
      ServerIOT.Endpoint,
      Supervisor.child_spec(%{id: Server.Liveness, start: {Server.Liveness, :start_link, []}}, type: :worker)
    ]

    opts = [strategy: :one_for_one, name: Server.Supervisor]
    Supervisor.start_link(children, opts)
  end

  # Tell Phoenix to update the endpoint configuration
  # whenever the application is updated.
  def config_change(changed, _new, removed) do
    ServerWeb.Endpoint.config_change(changed, removed)
    :ok
  end
end

很明显,改变了你的名字。Server.Liveness可能只是一个临时的gen_server,它只做这个,在启动时写文件,然后正常退出。

相关问题