Enabling Distributed Elixir on Google App Engine

Tags

Train platform

Google App Engine is a Platform-as-a-Service (PaaS) for applications where you simply deploy without needing to worry about typical operations such as server management, networking, and scaling. You can scale applications by increasing the number of instances running your applications, with the benefit of those instances running behind a load balancer. Since Elixir has the power of the BEAM with the ability to connect nodes, why not enable distributed Elixir and let our application behave like it’s on one large machine?

Let’s see how we can enable distributed Elixir on Google App Engine.

Clustering Instances

For clustering instances together automatically, we can leverage libcluster. libcluster will automatically connect our nodes dynamically without any manual intervention.

To tell libcluster how to cluster nodes together, there are strategies that coordinate how nodes should be discovered and connected. For Google App Engine support, I’ve created a new strategy in libcluster_gae. This clustering strategy will automatically connect nodes on instances that are running and are configured to receive HTTP traffic.

Configuring The Application

Add libcluster_gae to your application’s dependencies.

def deps do
  [
    {:libcluster_gae, "~> 0.1"}
  ]
end

Define a topology for libcluster using the Google App Engine clustering strategy.

# prod.exs
config :libcluster,
  topologies: [
    my_app: [
      strategy: Cluster.Strategy.GoogleAppEngine
    ]
  ]

Add a cluster supervisor to your application’s supervision tree.

defmodule MyApp.App do
  use Application

  def start(_type, _args) do
    topologies = Application.get_env(:libcluster, :topologies)

    children = [
      {Cluster.Supervisor, [topologies, [name: MyApp.ClusterSupervisor]]},
      # ...
    ]
    Supervisor.start_link(children, strategy: :one_for_one, name: MyApp.Supervisor)
  end
end

Update your release’s vm.args file.

## Name of the node
-name <%= release_name%>@${GAE_INSTANCE}.c.${GOOGLE_CLOUD_PROJECT}.internal

## Limit distributed erlang ports to a single port
-kernel inet_dist_listen_min 9999
-kernel inet_dist_listen_max 9999

Update the app.yaml configuration file for Google App Engine.

env_variables:
  REPLACE_OS_VARS: true

network:
  forwarded_ports:
    # epmd
    - 4369
    # erlang distribution
    - 9999

Enable the App Engine Admin API for your Google Cloud project.

Video showing how to enable the App Engine Admin API

Now run gcloud app deploy to start clustering your application.

Wrap Up

libcluster is a straightfoward way to cluster nodes, and libcluster_gae enables clustering for Google App Engine. Hopefully this will allow you better utilize your instances’ resources by allowing the BEAM to treat the application like it’s running on one large machine.

For futher reading, check out the libcluster documentation as well as the libcluster_gae documentation.

DockYard is a digital product agency offering exceptional user experience, design, full stack engineering, web app development, custom software, Ember, Elixir, and Phoenix services, consulting, and training.