Connecting Elixir app with Vert.X microservices

234 views
Skip to first unread message

Chintan Mishra

unread,
Oct 5, 2017, 8:33:58 AM10/5/17
to vert.x

The project owner's infrastructure we are building heavily demands concurrent systems to handle multiple web requests. So our team's first choice was going for Elixir/Erlang. Now that we have built most of our services using Elixir/Erlang we faced an issue with ArangoDB drivers in Elixir. And for this one particular issue, we found the optimal* solution given our constraints and it exists within the Vert.X drivers for ArangoDB. So now my question how we can connect our Elixir app to Vert.X app? Our first choice would be using JavaScript.

How to pass messages from Elixir app to Vert.X and vice versa?

*
Following constraints: project demands concurrent systems, we have already built a large part of Elixir/Erlang, Vert.X and Foxx framework for ArangoDB were our two choices. We chose Vert.X as it brings lots of benefits related to concurrency on the table. Yes, we can work with passing JSON/MsgPack over socket connection or MQTT broker or Apache Kafka. But we were hoping to get high-level pseudo code overview for passing messages between Vert.X and Elixir using Ports or any other method in Elixir, as it serves as the application backbone.

Paulo Lopes

unread,
Oct 5, 2017, 9:59:58 AM10/5/17
to vert.x
Given that I've no experience on Elixir, I'd imagine that if someone would be up to implement a eventbus bridge e.g.:

https://github.com/vert-x3/vertx-tcp-eventbus-bridge/

one could send and receive messages across elixir <-> vertx.

The implementation is not complex as if you deploy this bridge (TCP) a reference implementation in javascript:

https://github.com/vert-x3/vertx-tcp-eventbus-bridge/blob/master/src/client/nodejs/lib/tcp-vertx-eventbus.js

Chintan Mishra

unread,
Oct 5, 2017, 11:57:29 AM10/5/17
to vert.x
Elixir/Erlang natively provide options to start various processes. Here are few methods which are particularly used for interoperability

Ports: allow external programs to be treated like any other Erlang process
Nifs: NIF library is dynamically linked into the emulator process, this is the fastest way of calling C-code from Erlang
Jinterface: gives us interoperability with the Java Virtual Machine ( Redirect to Jinterface library docs on Erlang's website )

I am interested in getting an idea how I can use JInterface for interoperability between Elixir/Erlang and JavaScript.

Chintan Mishra

unread,
Oct 5, 2017, 12:12:49 PM10/5/17
to vert.x
The EventBus solution you presented feel like keeping Socket connections.

I have been doing a little bit of research of my own.

It would be helpful if you can verify my approach. Through Kotlin we can call JavaScript and it appears so that Kotlin can easily use Java libraries. So my plan of action is connect Elixir/Erlang with Kotlin using JInterface. And this Kotlin code interfaces with whatever JavaScript Vert.X code we have. Does it sound doable or can you identify some flaws?

Jez P

unread,
Oct 5, 2017, 2:41:07 PM10/5/17
to vert.x
What do you mean by "Through Kotlin we can call JavaScript"? You can transpile kotlin to javascript, but that doesn't run in the JVM (you can use Nashorn to execute javascript in the jam, however).

If you use Interface you can use java directly to talk to vertx, but ultimately if in separate processes, I would say use a socket connection for that. What's your fundamental problem with that? It's a fairly standard pattern in the micro services world. 

Chintan Mishra

unread,
Oct 5, 2017, 11:55:35 PM10/5/17
to vert.x
Socket connections are reliable but choosing other methods over socket connections is preferred personally by me bacause interoperability between languages gives much more control to a programmer when considering failover strategies. And I give a lot of weightage to cases where systems(apps) were communicating but due to crash in either one the app is continuously sending RPC requests and taking up useless memory. Interoperability allows apps to know if there is a failure and then either restarting the process where it crashed or restarting it from the start  or even sending the task to other running process or whatever suits your use-case. In the end mostly interoperability is message passing with much more supervision and control. Hope this answers the problem that I have with Sockets.

This is what I meant when I said "Through Kotlin we can call JavaScript".

Chintan Mishra

unread,
Oct 6, 2017, 12:00:54 AM10/6/17
to vert.x
Also, interoperability reduces the chances of errors between teams building infrastructure using MicroService Architecture. Eventually, the teams end up communicating which helps build newer ideas and independent microservices don't have to worry about Socket connections and network failure. The major concern shifts towards preventing application failure.

Jez P

unread,
Oct 6, 2017, 1:22:36 AM10/6/17
to vert.x
Your link is talking about Kotlin transpiling to JavaScript, not compiling to JVM bytecode. That will not give you the ability to run vert.x the way you want. Vert.x is a JVM technology. Kotlin can be used to compile directly to Java. If you're using JVM interop as you suggest, why throw JavaScript into the mix!

And thanks for telling me about micro service architectures. I had no idea sockets could be unreliable ;) One question for you: if you build a distributed system so you can scale horizontally, how will your services communicate without carrying that risk of network failure?

Jez P

unread,
Oct 6, 2017, 4:42:32 AM10/6/17
to vert.x
What I'm also not clear on is why not just use the java driver for ArangoDB directly from a Java application? In terms of message passing then you just read your messages from stdin and write responses to stdout (that's how the ports stuff works in Elixir, from a quick read). I'm not sure you need vert.x in there at all,. If you feel there's a benefit, then embed vert.x in your Java app which reads from std in, puts messages on the event bus, then when it receives messages back, writes them to std out (but if you go down this route, be wary of anything logged to stdout). 

So the pseudo code is
Listen on stdin
When you get messages from your Elixir app, do any routing needed and write to the vert.x event bus as needed.
Your ArangoDB layer does its stuff and writes out responses to the event bus
You listen on the event bus for these responses and write them to stdout.

Paulo Lopes

unread,
Oct 6, 2017, 4:58:23 AM10/6/17
to vert.x
So what "other" methods can an elixir app use? (again i know nothing about elixir) are talking about:

communicating over:

* gRPC ?
* domain sockets ?
* SDTIN/STDOUT ?
* pipes ?
* HTTP 1.1/2 ?
* WebSockets ?
* something else ?

Chintan Mishra

unread,
Oct 6, 2017, 6:47:06 AM10/6/17
to vert.x
@paulo
Methods you mentioned are usually available for almost all microservices. Do let me know if I am missing something in your reply.

@JezP
Regarding your question about scaling horizontally.
We build one monolithic application which in itself is constituted by many microservices which communicate with one another through interoperability features available within the language. Instead of deploying multiple instances of microservices we make do by installing one monolithic multi language app in each Docker instance. Whenever our needs grow Kubernetes powers up a new instance of our complete application in a new Docker instance. Let me know what you think about this. We haven't had many discussions with anyone related to this.

Regarding using Foxx or Vert.X not Java drivers.
ArangoDB has a hard time storing Blobs or binaries in DB. For this we instead store path to file in the DB. Now if an ArangoDB cluster is powered up then the path become dependent on network, IP of the cluster, and other things. This problem further grows if we bring in replication over vast geolocations. In order to solve this the colution is available in Foxx framework and Vert.X. Due to large number of Vert.X we a re preferring it.

Hope this answers.

Jez P

unread,
Oct 6, 2017, 7:40:16 AM10/6/17
to vert.x
Multiple monoliths are ok if you 
(1) Don't care about tightly coupling everything in your deployment
(2) Don't want to scale independently
Also note that you're going to be fundamentally dependent on sockets to talk to your database, so you can't absolve yourself of dealing with network problems. I'm not convinced that there's a lot more pain in adding a socket-based connection to a vert.x application which then talks to your db via another socket connection. But it's your problem, not mine, so you own the solution. 

Anyway, you've had my opinion, and pseudo code, so I'll leave managing the complexity that I think will arise up to you. Ultimately it's your application, so go for it. Good luck. 

Chintan Mishra

unread,
Oct 6, 2017, 10:35:44 AM10/6/17
to vert.x
Okay. That is informative. I think I gave a bad explanation above monoliths being tightly coupled. Each monolith serves only few(generally within 5 or so) closely related purposes. The monolith under heavy workload gets a new instance powered up by Kubernetes. And yes here we do use sockets to communicate between moniliths. Our first action is not to jump towards building up a solution using network connections but to take some interest in the insides of other languages/frameworks as well. It does make things hard for the first time but on the long we haven't faced any thing but ease in maintaining.

I believe I exactly have what I reached out for. I am grateful for your help @JezP and @PauloLopes

On an ending note view this video on YouTube if interoperability got your interest: https://www.youtube.com/watch?v=b-xwM4i62q4

Alexander Lehmann

unread,
Oct 9, 2017, 7:11:23 AM10/9/17
to vert.x
It should be possible to talk between elixir and vert.x via the Ports, however since there is no protocol implemented on the vert.x part, you would have to implement something yourself.

Assuming that Ports usually communicate via stdin/stdout, the erlang process could start a java process that reads and writes stdin/stdout in the main method and dispatches the sent messages to a Verticle or via eventbus or just calls async methods. This way, each instance of your main erlang vm would have a jvm process attached that runs the vert.x operations and not a vert.x cluster that communicates via the event bus.

If you pass your messages as JSON, a simple request/response protocol with async messages would probably be ok (e.g. each request is a JSON object with a message-id and the reponse is either the result or an error as JSON with the same message-id) and would fit the async concept of vert.x quite well (I have not much experience with erlang, but the message passing concept should be fitting as well)



On Thursday, October 5, 2017 at 2:33:58 PM UTC+2, Chintan Mishra wrote:

Chintan Mishra

unread,
Feb 22, 2018, 1:53:43 AM2/22/18
to vert.x
A follow up question. As Vert.X is polyglot would it be possible to have Vert.X for Elixir? Please also add some comments on if it'd be logical to have one for Vert.X.

Julien Viet

unread,
Feb 22, 2018, 10:41:27 AM2/22/18
to ve...@googlegroups.com
Hi,

I'm afraid this is not possible because Vert.x runs on the JVM and Elixir on Erlang VM.

Julien

-- 
You received this message because you are subscribed to the Google Groups "vert.x" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vertx+un...@googlegroups.com.
Visit this group at https://groups.google.com/group/vertx.
To view this discussion on the web, visit https://groups.google.com/d/msgid/vertx/ab8e9def-f701-4542-a499-1df19cb6cdf5%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages