O'Reilly Book Excerpts: JXTA in a Nutshell
Getting Started with JXTA, Part 4
In part four in this series of book excerpts from JXTA in a Nutshell, learn about JXTA pipes.
One of the most powerful of JXTA's services is the pipe service. The idea of a pipe is familiar to users of Unix systems: a pipe is used to connect the output from one command to the input of another command. On a Unix system, if you want to count the number of unique exceptions that occur in a log file, you might use this command:
piccolo% cat log | grep "Exception" | sort | uniq | wc -l
cat command prints the log file to its standard output. The
grep command reads this file from its standard input and searches for lines containing the string "Exception"; it prints matching lines to its standard output. The
sort command reads these lines from its standard input and sends the sorted list to its standard output, where it is read by the
uniq command, which removes duplicate lines. The unduplicated lines are sent to its standard output, where they are read by the
wc command, which counts the number of lines and finally prints that number.
Pipes are quite useful in that they allow you to build complex functionality from a number of simple building blocks. JXTA takes the familiar idea of pipes and extends their functionality to the network.
In This Series
Getting Started with JXTA, Part 2
JXTA pipes are defined in terms of the endpoints available to a peer. A peer endpoint is a logical abstraction of an address on a network transport that is capable of sending and receiving network messages. In the examples we've seen so far, the network transport has always been IP-based: the shell peer we've looked at has a TCP endpoint (port 9701 by default) and can have an HTTP endpoint. However, JXTA does not make this assumption and allows an endpoint to be an address on any network transport as long as the network is capable of sending and receiving datagram-style (i.e., unreliable packet-based) messages.
In the shell, the available endpoints are established when the configurator runs. The TCP endpoint is based on the network address selected from the pull-down menu and the port number entered into the TCP port text box; the HTTP endpoint is enabled by selecting support for HTTP.
In JXTA, pipes provide a unidirectional, virtual connection between two pipe endpoints: input pipe (receiving end) and output pipe (sending end). Pipe connections are established independently of the pipe endpoints peer location. For example, the input pipe endpoint can be located behind a firewall or NAT while the output endpoint can be located on a peer on the Internet. The endpoints may even be on physically different networks: the input pipe endpoint could be on a TCP network while the output pipe endpoint is on a token ring network. As long as there are available JXTA relay peers between the two endpoints, a logical pipe between them may be defined.
Therefore, pipes enable connections without any consideration of connectivity. Two peers may require an intermediary routing peer to communicate between each other. Pipes virtualize peer connections to homogenize and provide an abstraction of the full connectivity available within the JXTA network.
Pipe connections are layered on top of the peer endpoint connections, as we show in Figure 2-4. This figure shows a set of peer endpoint connections: Peer B, for example, has two HTTP endpoint connections while Peer D has two HTTP endpoint connections and one TCP/IP endpoint connection.
Note that some peers sit behind a firewall. HTTP proxy connections are used to connect to a peer outside the firewall (a TCP/IP Socks connection could also have been used). Peer C and Peer A can act as router peers for peers behind firewalls.
A pipe connection may involve multiple peer endpoint transport connections (multi-hops). The pipe connection between Peer B and Peer E involves an HTTP connection between Peer B and Peer C, an HTTP connection between Peer C and Peer D, and a TCP/IP connection between Peer D and Peer E. On the other hand, if a pipe connection is established between Peer A and Peer C, a single peer endpoint connection will implement the pipe, as Peer A and Peer C have a direct TCP/IP connection.
Pipes may send messages in different ways, each of which may provide a different quality of service. Some examples of this include:
Unidirectional, asynchronous: The pipe endpoint sends a message, and no guarantee of delivery is made.
Synchronous request/response (RPC): The pipe endpoint sends a message and receives a correlated answer.
Publish/subscribe: A pipe endpoint subscribes to messages sent from a publisher endpoint.
Bulk data transfer: The pipe provides reliable data transfer of binary data.
Streaming: The pipe provides efficient data transfer over a flow-controlled channel.
The default service provided by a JXTA pipe is unidirectional, asynchronous communication. All other pipe services can be implemented by the developer either directly on top of the peer endpoints or over the default pipe abstraction. The unidirectional and asynchronous pipe service was selected as the minimum common denominator service easily implementable on a wide variety of non-IP transports. The asynchronous model was also selected since it fits well with the unreliable nature of a P2P network such as JXTA, in which peers or connections may disappear at any moment. Asynchronous models are also known to be more scalable (as the number of peers increase) than synchronous models. Finally, an asynchronous model provides an easier fault recovery and garbage collection mechanism when network connections fail.
Pipes provide a nonlocalized communication abstraction. Applications and services create pipe endpoints (an input pipe and an output pipe) to communicate independently of the pipe endpoints' peer location. Due to the unreliability and the interchangeable nature of peers in the JXTA network, pipes provide a powerful mechanism to build fault-tolerant applications. When creating a connection to a service, the pipe abstraction permits the peer to bind the pipe endpoints dynamically to the best or more appropriate instance of the service independent of the peer location. This hides the location of a service peer from the application, which is extremely important on an unreliable network.
Pages: 1, 2