low.sock

low.sock

Hi,

I’m currently running a Elixir application which leverages Phoenix channels. I’ve clustered my application together using libcluster but my application gets intermittent warnings about node disconnects. This is an example of the message that I’m getting:

[warning] ‘global’ at node :“app name@ip” disconnected node :“app name@ip” in order to prevent overlapping partitions

I have also had users raise issues about de-sync, which would make me believe that this is an issue.

I’ve deployed my application on Fly.io and it seems that the nodes that are farther from every other node disconnect more often. For instance, most of my servers are in North America and Europe but my node in South America disconnects quite frequently, with my node in Australia being a close second. I’m running 20 nodes in total.

Basically what my question boils down to is what can I do about this? Is there a configuration that would allow node to wait longer for a response from other nodes? I know there Erlang flags but I wanted to ask here first if those would be a good idea and how could I go about adding these on a Dockerfile (which Fly uses to deploy the application).

Sorry for the long post and any advice would be much appreciated :slight_smile:

Edit: just fixed some formatting in the post

Showing Posts 1 to 10

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

It is my understanding that distributed erlang is not really built for geographically distributed clusters by default. These connections are not (as you have observed) the most reliable, and this leads to partitioning and other problematic behavior.

This seems pretty high, can you talk about the load that you see?

low.sock

low.sock OP

So would Redis clustering be the way to go?

I have 20 nodes because Fly doesn’t have auto-scaling for their Apps v2 platform, you have to pre-allocate your machines

low.sock

low.sock OP

Cool, would this configured inside the runtime file in the Elixir app?

asabil

asabil

Yes, something like this should work:

config :kernel,
  net_ticktime: 120
low.sock

low.sock OP

Thanks, I did try that but I get the following:

Cannot configure base applications: [:kernel]

These applications are already started by the time the configuration
executes and these configurations have no effect.

If you want to configure these applications for a release, you can
specify them in your vm.args file:

-kernel config_key config_value

Alternatively, if you must configure them dynamically, you can wrap
them in a conditional block in your config files:

if System.get_env("RELEASE_MODE") do
  config :kernel, ...
end

and then configure your releases to reboot after configuration:

releases: [
  my_app: [reboot_system_after_config: true]
]

This happened when loading config/config.exs or
one of its imports.

I’m going to try and set it through the vm.args.eex file. Is there a command I can use with iex to check the net_ticktime? I’ve been doing some searching but nothing is jumping out at me

hst337

hst337

It appears that nodes just lose connection from time to time

This is what global source code says about it:

%% ----------------------------------------------------------------
%% Prevent Overlapping Partitions Algorithm
%% ========================================
%%
%% 1. When a node lose connection to another node it sends a
%%    {lost_connection, LostConnNode, OtherNode} message to all
%%    other nodes that it knows of.
%% 2. When a lost_connection message is received the receiver
%%    first checks if it has seen this message before. If so, it
%%    just ignores it. If it has not seen it before, it sends the
%%    message to all nodes it knows of. This in order to ensure
%%    that all connected nodes will receive this message. It then
%%    sends a {remove_connection, LostConnRecvNode} message (where
%%    LostConnRecvNode is its own node name) to OtherNode and
%%    clear all information about OtherNode so OtherNode wont be
%%    part of ReceiverNode's cluster anymore. When this information
%%    has been cleared, no lost_connection will be triggered when
%%    a nodedown message for the connection to OtherNode is
%%    received.
%% 3. When a {remove_connection, LostConnRecvNode} message is
%%    received, the receiver node takes down the connection to
%%    LostConnRecvNode and clears its information about
%%    LostConnRecvNode so it is not part of its cluster anymore.
%%    Both nodes will receive a nodedown message due to the
%%    connection being closed, but none of them will send
%%    lost_connection messages since they have cleared information
%%    about the other node.
%%
%% This will take down more connections than the minimum amount
%% of connections to remove in order to form fully connected
%% partitions. For example, if the user takes down a connection
%% between two nodes, the rest of the nodes will disconnect from
%% both of these nodes instead of just one. This is due to:
%% * We do not want to partition a remaining network when a node
%%   has halted. When you receive a nodedown and/or lost_connection
%%   messages you don't know if the corresponding node has halted
%%   or if there are network issues.
%% * We need to decide which connection to take down as soon as
%%   we receive a lost_connection message in order to prevent
%%   inconsistencies entering global's state.
%% * All nodes need to make the same choices independent of
%%   each other.
%% 
%% ----------------------------------------------------------------

So, the real question is are you sure that the connection between nodes is not lost from time to time? If you’re sure, what tool do you use to check it?

schneebyte

schneebyte

If you don’t need global then i would set prevent_overlapping_partitions to false https://www.erlang.org/doc/man/kernel_app.html#prevent_overlapping_partitions

And depending on how many messages you’re sending between nodes you might want to increase the distribution buffer busy limit as well, default is only 1 MB

Also net_setuptime https://www.erlang.org/doc/man/kernel_app.html#net_setuptime

You can use Application.get_env(:kernel, :net_ticktime) to check the value.

low.sock

low.sock OP

Thanks everyone for the tips. I’m testing the different configurations and adding a little more monitoring so I can more easily see improvements. I’ll update again once I’ve seen some improvements :slight_smile:

chasers

chasers

Also very interested in the ideal global config.

We see a lot of packet loss between regions on Fly depending on the region and have managed to only get 4 regions (8 nodes) running somewhat reliably.

Had to build latency monitoring. See: Realtime Status

It logs latencies to our logging infra too if they are over a threshold.

Note: the default PubSub adapter sends all messages to all nodes.

The Redis adapter would route everything through one box which would negate the whole global cluster idea.

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
jonnycharles
I’m in search of an Elixir library that offers PDF generation capabilities similar to Ruby’s Prawn. While there have been discussions abo...
New
spammy
I’m looking to build a personal workflow to quickly deploy web applications written in elixir/phoenix, for local consumption (ie not on t...
New
dli
Before I dive in myself, did anyone successfully sprinkle Hologram into their existing LiveView app? Looking for hints regarding: Addi...
New
roeland
Kia ora, We have been using elixir-google-api to connect to Google Drive. However, with the updates to Tesla due to CVEs this is now bro...
New
bottlenecked
Hi all, I wanted to ask how the community is dealing with post-release steps. Today we have Ecto migrations, which make sure that the db...
New
rahultumpala
Hello, I have an Elixir backend that implements a custom protocol over TCP. I want to load test the backend and assess the performance o...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
ausimian
Emily is an Elixir library that runs Nx computations on Apple’s MLX. Install it as the default Nx backend and Nx, defn, Axon, Nx.Serving,...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews