Packages
libcluster_gce
0.0.1
Clustering strategy for connecting nodes running on Google App Engine.
Current section
Files
Jump to
Current section
Files
lib/cluster_gce/strategy/labels.ex
defmodule ClusterGCE.Strategy.Labels do
@moduledoc """
Clustering strategy for Google Compute Engine.
This strategy checks for the list of app versions that are currently receiving HTTP.
For each version that is listed, the list of instances running for that version are fetched.
Once all of the instances have been received, they attempt to connect to each other.
**Note**: This strategy only connects nodes that are able to receive GCP internal DNS traffic
To cluster an application running in Google Compute Engine, define a topology for `libcluster`.
```elixir
config :libcluster,
topologies: [
my_app: [
strategy: ClusterGCE.Strategy.Labels,
config: [
polling_interval: 10_000,
project_id: "my-project",
label: "my-app:environment-name"
]
]
]
```
## Configurable Options
Options can be set for the strategy under the `:config` key when defining the topology.
* `:polling_interval` - Interval for checking for the list of running instances. Defaults to `10_000`
* `:project_id` - Google Cloud project name
* `:label` - A key value map of instance labels to match
### Release Configuration
Update your release's `vm.args` file to include the following lines.
```
## Name of the node
-name <%= release_name%>@${GOOGLE_COMPUTE_ENGINE_INSTANCE}.${GOOGLE_COMPUTE_ENGINE_ZONE}.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
```
Run your application with the environment variable `REPLACE_OS_VARS=true` and forward the following tcp ports:
- `4369 # epmd`
- `9999 # erlang distribution`
```
"""
use GenServer
use Cluster.Strategy
alias Cluster.Strategy.State
def start_link(args) do
GenServer.start_link(__MODULE__, args)
end
@impl true
def init([%State{} = state]) do
{:ok, load(state)}
end
@impl true
def handle_info(:timeout, state) do
handle_info(:load, state)
end
def handle_info(:load, %State{} = state) do
{:noreply, load(state)}
end
def handle_info(_, state) do
{:noreply, state}
end
defp load(%State{} = state) do
connect = state.connect
list_nodes = state.list_nodes
topology = state.topology
{:ok, nodes} = ClusterGCE.get_nodes(state)
Cluster.Strategy.connect_nodes(topology, connect, list_nodes, nodes)
Process.send_after(self(), :load, polling_interval(state))
state
end
@default_polling_interval 10_000
defp polling_interval(%State{config: config}) do
Keyword.get(config, :polling_interval, @default_polling_interval)
end
end