TomGrozev

TomGrozev

Microservice node communication with Phoenix

I am trying to setup elixir in a microservice architecture and have each of them (i.e. nodes) communicating efficiently. For context, there is a product microservice and a phoenix frontend microservice (there are more but these are relevant). I have got them connected through some custom module that is a dependency on both. This code basically spawns a task locally to spawn a task on another service to do whatever (i.e. create a product), this works great using a call similar to Connector.call(ProductMicroService.Products, :create, [some_product]). The downfall of this is when it comes to using Ecto schemas in Phoenix since it will try to call the schema module functions (e.g. struct) locally and not in the products microservice where the schema actually exists.

Now I have a couple possible solutions but none of them seem to appetizing and all seem very ‘hacky’. Some ideas I had are:

  1. Create copies of the schema modules on the frontend microservice
  2. Create fake schema modules on the frontend microservice that has all the functions but redirects calls the the real schema module
  3. Override the relevant functions in Phoenix (there are a lot)
  4. Some alternative?

For the more synchronous calls I believe the direct node communication is best and for asynchronous things a message queue (RabbitMQ, etc.) but is there a better way that I am missing? Anyway this is done, Phoenix still needs to be able to access these methods on the schema. It doesn’t seem to be an issue with anything other than phoenix.

Most Liked

Laetitia

Laetitia

In microservices architecture, the microservices share “raw data”, i.e the interfaces can expose maps, not struct. Each microservice must have its “view” of the model. For instance, a product in microservice A may have some different attributes from a product in microservice B. The output of microservice A will be a map, and microservice B will receive this map and convert it to its struct or schema.
Phoenix offers a backend-template application, so you don’t need microservices and you can use the schema along all your application but if you really need microservices, it’s a good way to use Erlang node communication and to apply decoupling between them.

al2o3cr

al2o3cr

Option 4: follow the first rule of distributed objects and don’t divide the system up this way.

AFAIK there aren’t any common patterns that would recommend turning context or view functions into remote procedure calls. Code in the “frontend” should interact with the “backend” via a clearly-defined API.

One other thing worth thinking about: the remote Task.Supervisor is single-threaded, so unless you add a lot of complexity that can be a bottleneck at high concurrency.

al2o3cr

al2o3cr

The phrasing is a little flippant, but the message is serious. Imposing a network boundary where there was only a module boundary before has significant costs:

  • duplication (for things like data definitions)
  • latency (network calls take time)
  • fallibility (network calls can fail)
  • deploy complexity (network calls may interact with servers that are a different version)

The biggest hazard in building a distributed system is that you get all of those headaches automatically, but you only get the good stuff (independent scaling, independent deploy, etc) with the right implementation.

For instance, an Elixir novice who confuses GenServer with “a server” and makes each piece of their application a single GenServer will produce a single-threaded performance tarpit.

The “rule” is a reminder to carefully consider the consequences of your decisions - what are you getting in exchange for all the additional complexity?

Where Next?

Popular in Questions Top

sergio
In Ruby, I can go: User.find_by(email: "foobar@email.com").update(email: "hello@email.com") How can I do something similar in Elixir? ...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
dotdotdotPaul
Okay, I’m having a heck of a time trying to figure out how to best handle the validation of belongs_to associations in Ecto. I’m sure I’...
New

Other popular topics Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
svb
Hi! Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New

We're in Beta

About us Mission Statement