Connecter Erlang, Julia, Elixir
C'est mon petit projet ambitieux pour connecter les différents mondes d'Erlang/Elixir et Julia :
Désormais, les processus Erlang et Elixir peuvent s'envoyer des messages puisqu'ils s'exécutent sur la même plate-forme BEAM et partagent des PID. Mais que diriez-vous d'envoyer des messages à Julia et de les renvoyer à Erlang/Elixir ?
Dans Julia REPL, nous démarrons une tâche pServer
, qui, à la demande, génère une tâche EvalServer
avec son propre espace de noms de module.
julia > using Erjulix, Sockets
julia > pServer ( 6000 )
Task (runnable) @ 0x0000000110b30ab0
Dans Elixir REPL, nous demandons un Julia EvalServer
et l'utilisons pour évaluer les expressions Julia ou pour appeler des fonctions Julia.
iex ( 1 ) > { :ok , jl , _ } = :ejx_udp . srv ( 6000 ) # get an eval server from Julia
{ :ok , { { 127 , 0 , 0 , 1 } , 54465 } , "Main.##esm#257" }
iex ( 2 ) > :ejx_udp . eval ( jl , "using .Threads" )
{ :ok , [ ] }
iex ( 3 ) > :ejx_udp . call ( jl , :threadid )
{ :ok , 3 }
iex ( 4 ) > :ejx_udp . call ( jl , :factorial , [ 50 ] )
{ :error ,
"OverflowError( " 50 is too large to look up in the table; consider using `factorial(big(50))` instead " )" }
iex ( 5 ) > :ejx_udp . eval ( jl , """ # define a function on the Julia server
...(5)> function fact(x)
...(5)> factorial(big(x))
...(5)> end
...(5)> """)
{:ok, "Main.##esm#257.fact"}
iex(6)> :ejx_udp.call(jl, :fact, [50])
{:ok, 30414093201713378043612608166064768844377641568960512000000000000}
iex(7)> :timer.tc(:ejx_udp, :call, [jl, :fact, [55]])
{527,
{:ok,
12696403353658275925965100847566516959580321051449436762275840000000000000}}
Le dernier timing montre que le ping-pong pour appeler la fonction fact
Julia créée avec les données d'Elixir et récupérer le résultat prend environ 500 µs avec les deux sessions exécutées sur la même machine (MacBook Pro).
iex ( 8 ) > a = Enum . map ( 1 .. 10 , fn _ -> :rand . uniform ( ) end )
[ 0.9414436609049482 , 0.08244595999142224 , 0.6727398779368937 ,
0.18612089183158875 , 0.7414592106015152 , 0.7340558985797445 ,
0.9511971092470349 , 0.7139960750204088 , 0.31514816254491884 , 0.94168140313657 ]
iex ( 9 ) > :ejx_udp . set ( jl , :a , a ) # create variable a on the Julia server
{ :ok , [ ] }
De retour dans le Julia REPL :
julia > exmod = Erjulix . _ESM[ 1 ] # get access to the server module
Main. # #esm#257
julia > exmod . a # and to the created variable a
10 - element Vector{Any} :
0.9414436609049482
0.08244595999142224
0.6727398779368937
0.18612089183158875
⋮
0.9511971092470349
0.7139960750204088
0.31514816254491884
0.94168140313657
julia > using Plots ....
Si nous démarrons notre pServer
avec l'adresse IP de la machine et une clé, la communication avec les clients distants est cryptée en SHA-256 :
julia > getipaddr ()
ip " 192.168.2.113 "
julia > key = Erjulix . genpasswd ( 12 )
" 1XQeFem2NUNw "
julia > pServer ( getipaddr (), 6000 , key)
Task (runnable) @ 0x00000001110e7b90
Nous utilisons l'adresse IP de la machine et cette clé pour accéder au pServer
depuis un Raspberry Pi dans le réseau local :
iex ( 1 ) > :inet . gethostname ( )
{ :ok , 'raspberrypi' }
iex ( 2 ) > key = "1XQeFem2NUNw"
"1XQeFem2NUNw"
iex ( 3 ) > { :ok , jl , _ } = :ejx_udp . srv ( { { 192 , 168 , 2 , 113 } , 6000 , key } )
{ :ok , { { 192 , 168 , 2 , 113 } , 55052 , "j8Gh3G6dPfJm28UpthL0dXew" } , "Main.##esm#258" }
iex ( 4 ) > :ejx_udp . call ( jl , :factorial , [ 20 ] )
{ :ok , 2432902008176640000 }
iex ( 5 ) > :timer . tc ( :ejx_udp , :call , [ jl , :factorial , [ 20 ] ] )
{ 86620 , { :ok , 2432902008176640000 } }
Le pServer
a généré une nouvelle clé pour l'accès réseau crypté au Julia EvalServer
. Le timing montre que le ping-pong réseau a pris moins de 100 ms entre les deux machines (sans cryptage, cela prend environ 70 ms).
iex ( 9 ) > :ejx_udp . client ( jl , :exit )
{ :ok , :done }
Il s'agit d'un prototype d'interopérabilité basé sur le format de terme d'Erlang sur UDP.
Sécurité des threads : bien sûr, l'accès au module serveur comme démontré n'est pas sécurisé pour les threads et ne doit donc pas être effectué simultanément.
Sécurité : si vous partagez des adresses et des ports de serveur UDP, un client distant peut accéder au système de fichiers. Si vous fournissez une clé au pServer
, les transmissions de données utiliseront le cryptage SHA-256.
ErlangTerm.jl
.jwerl
, compatible avec Erlang/OTP 24. Il y a un problème pour mettre à jour le repo principal. Lorsqu'il est disponible dans le registre Julia, vous pouvez installer le package avec
pkg > add Erjulix
S'il est disponible en Hex, le package peut être installé dans Elixir en ajoutant erjulix
à votre liste de dépendances dans mix.exs
:
def deps do
[
{ :erjulix , "~> 0.1.0" }
]
end
La documentation peut être générée avec ExDoc et publiée sur HexDocs. Une fois publiés, les documents peuvent être trouvés sur https://hexdocs.pm/erjulix.