forked from doublec/factor-articles
-
Notifications
You must be signed in to change notification settings - Fork 1
/
distributed_channels.tex
108 lines (84 loc) · 3.17 KB
/
distributed_channels.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
\chapter{Distributed Channels}\label{dchannels}
Remote Channels are distributed channels that allow you to access
channels in separate Factor instances, even on different machines on
the network.
\wordtable{
\vocabulary{channels.remote}
\ordinaryword{<remote-channel>}{<remote-channel> ( node id -- remote-channel )}
\ordinaryword{publish}{publish ( channel -- id )}
}
A channel can be made accessible by remote Factor nodes using the
\texttt{publish} word. Given a channel this will return a unique
identifier that can be used by remote nodes to use the channel. For
example:
\begin{verbatim}
USING: fry threads channels channels.remote ;
: (counter) ( channel n -- )
[ swap to ] [ 1 + (counter) ] 2bi ;
: counter ( channel -- )
2 (counter) ;
<channel> dup '[ _ counter ] "counter" spawn drop publish .
=> 12345678901234567890.....
\end{verbatim}
Remote channels are implemented using
distributed concurrency so you must start a node on the Factor
instance you are using. This is done with `start-node' giving the
hostname and port:
\wordtable{
\vocabulary{concurrency.distributed}
\ordinaryword{start-node}{start-node ( port -- )}
}
\begin{verbatim}
USE: concurrency.distributed
9000 start-node
\end{verbatim}
Once this is done all published channels become available. Note that
the hostname and port must be accessible by the remote machine so it
can connect to send the data you request.
From a remote node you can create a \texttt{<remote-channel>} which contains
the hostname and port of the node containing the channel, and the identifer
of that channel.
You can use `from' and `to' on the remote channel exactly as you can
on normal channels. The data is marshalled over the network using the
serialization library.
\begin{verbatim}
USING: io.sockets ;
"127.0.0.1" 9000 <inet4> 1234... <remote-channel> from .
\end{verbatim}
One way of setting up remote channel services is to serialize an instance of a \texttt{<remote-channel>} for a published channel and make it available on an HTTP server. The remote nodes can retrieve this via HTTP, deserialize it and use it. You can test this on a local machine by running two factor instances. In instance 1:
\begin{verbatim}
USING:
fry
io.encodings.binary
threads
concurrency.distributed
channels
channels.remote
serialize
;
9000 start-node
: (counter) ( channel n -- )
[ swap to ] [ 1 + (counter) ] 2bi ;
: counter ( channel -- )
2 (counter) ;
<channel> dup '[ _ counter ] "counter" spawn drop
publish local-node get swap <remote-channel>
"counter.ser" binary [ serialize ] with-file-writer
\end{verbatim}
This creates a channel that returns incrementing integer numbers, as per our previous examples. A \texttt{<remote-channel>} is created with the published identifier for this channel and our node address. This is serialized to a file called ``counter.ser''. A remote node can deserialize this file and use it to access the channel immediately. In factor instance 2:
\begin{verbatim}
USING:
io.encodings.binary
threads
concurrency.distributed
channels
channels.remote
serialize
;
9001 start-node
"counter.ser" binary [ deserialize ] with-file-reader
dup from .
=> 2
dup from .
=> 3
\end{verbatim}