Overview

HTTPS SSH

mbxchan - Simple, distributed Go channels and remote methods.

This package enables easy construction of distributed Go applications. Application processes communicate through standard Go channels. The package also provides simple access to exported remote methods (RPC).

Quick Start

Examples:

I. Send "Hello" from one process to another

Sending side:

outch, err := mbxchan.MakeClientChan("mybox")
outch <- []byte("Hello")
...
mbxchan.CloseClientChan(outch)

Receiving side:

inch, err := mbxchan.MakeServerChan("mybox", "HTTP");
body, ok <- inch
fmt.Printf("%s\n", string(body))
...
mbxchan.CloseServerChan(inch)

From the above:

  1. We use regular Go channels to send and receive data. The Go channels are mapped to process incoming Mailbox.

  2. The data is a binary blob ([]byte) - no limitations on format or contents.

  3. A symbolic name is used for the Mailbox. The name is unique within the distributed application instance, when all application instance processes use the same name service - Location Service. There could be a number of distributed application instances, each running its own Location Service.

  4. The locations of the Sender (Client) and Receiver (Server) are transparent - they can reside within the same process or be distributed (on one or separate hosts).

To enable Mailbox name resolution we need a name service. This is provided by the Location Service (LS) process. Choose a host, port number and run one instance of LS.

E.g., on host named "lshost" run the command:

$ mbx_ls 9999 &

To enable application processes to use the LS, call the function:

mbxchan.SetLsAddr("http://lshost:9999/")

before creating Mailbox channels (preferably in an init() function).

II. Synchronous RPC call of remote method by name "Mul"

User application data structure definition:

type MulStruct struct { A, B int }

Client side:

...
funcDesc := mbxchan.OpenRpcConn("Mul")
...
args := MulStruct{3, 4}
reply := new(int)
err := funcDesc.RpcCall(args, reply)

Server side:

...
err := mbxchan.PublishRpcMethod("Mul", CalcMul)
...

// Remote method on server side

func CalcMul(args interface{}) []byte {
    var mul Mul

    ret := mbxchan.RpcArgs(args, &mul)
    if ret != nil {
        return ret
    }
    c := mul.A * mul.B
    return mbxchan.RpcReply(c)
}

To perform remote method call, the calling process must know the remote method symbolic name. To enable RPC remote method name resolution we need a name service. This is provided by the Location Service (LS) process. See Example I.

III. Asynchronous RPC call of remote method by name "Mul"

In this example we perform asynchronous call of remote function "Mul" which was published in example II. Asynchronous call returns pointer to structure:

type rpcCall struct {
    Reply interface{}
    Error error
    Done  chan rpcCall
}

User application data structure definition:

type MulStruct struct { A, B int }

Client side:

...
funcDesc := mbxchan.OpenRpcConn("Mul")
...
args := MulStruct{3, 4}
reply := new(int)
mulCall := funcDesc.RpcGo(args, reply)
// Could be some processing here
replyCall := <-mulCall.Done
// NOTE: ALWAYS check reply Error before using reply values !!!
if replyCall.Error != nil {
    fmt.Printf("Mul Error:%s\n", replyCall.Error)
} else {
    fmt.Printf("result:%d\n", *replyCall.Reply.(*int))
}

Installation

$ hg clone http://bitbucket.org/levarnon/mbx
$ cd src/mbxchan
$ go install
$ cd ../src/mbx_ls
$ go install
$ cd ../src/mbx_tst
$ go install

Don't forget to run 'mbx_ls <port_no> &' before starting your mbxchan programs.

Details

mbxchan channels functionality is implemented through named Mailboxes (MBX). These Mailboxes provide unidirectional inter-process communication (one-to-one, many-to-one). Each Mailbox has a unique name.

Go channels of []byte type are mapped to the named Mailboxes. Through these Go channels application processes can receive and send network messages (binary blobs) using standard Go channel operations. MBX processes could be local or remote. Each application process can have an unlimited number of incoming Mailboxes.

To support mbxchan functionality Location Service (LS) instance must run. LS maintains a list of all active Mailboxes and can run on any host. When a Mailbox publishes itself on a Location Service, mbxchan refreshes Mailboxes's LS registration every ~~ 10 seconds. LS removes Mailbox entry from its registry when more than 20 seconds had elapsed since its last update. This ensures that "dead" mailboxes will not be advertised.

The Mailbox channels are unbuffered (synchronous), so senders will block till remote receiver will be ready to receive. The message will be transferred once the remote Mailbox becames active and publish itself on the Location Service. The same is true for the receiver, if no message was sent to the Mailbox the receiver will block.

A Mailbox's name starts with an alphabetic letter and followed by digits, letters, underscores and dashes.

mbxchan RPC remote methods functionality is implemented through named RPC remote methods. These remote methods could be accessed through synchronous and asynchronous RPC calls.

API

func SetLsAddr(lsAddr string) string

SetLsAddr defines the endpoint of Location Server. There is one Location Server per application process.

E.g: lsAddr = "http://192.168.3.99:9999/"

SetLsAddr must be called before creating application mailbox channels. Returns current lsAddr.

func MakeServerChan(mbxname, trans string) (chan []byte, error)

MakeServerChan creates a Go channel mapped to named Mailbox. The Mailbox name (mbxname) must be unique. The Mailbox will be registered on a Location Service. MakeServerChan returns incoming Go channel of []byte type and error.

  • mbxname - unique Mailbox name(e.g.: "appl_mbx"),
  • trans - Transport type: "HTTP" | "TCP" | "UDP" | "WEBSOCKET"

Only "HTTP" & "WEBSOCKET" transports are currently implemented.

func CloseServerChan(mbxch chan []byte) error

CloseServerChan - Close incoming Mailbox channel.

  • mbxch - mailbox channel created in MakeServerChan()

func MakeClientChan(mbxname string) (chan []byte, error)

MakeClientChan opens connection to a known named Mailbox. MakeClientChan returns an outgoing Go channel of []byte type and error.

  • mbxname - unique Mailbox name(e.g.: "appl_mbx")

func CloseClientChan(mbxch chan []byte) error

CloseClientChan - Close outgoing Mailbox channel.

  • mbxch - mailbox channel created in MakeClientChan()

func PublishRpcMethod(rpcname, rpcfunc rpcRef) error

PublishRpcMethod publishes an RPC method on Location Server (LS).

func UnpublishRpcMethod(rpcname string) error

UnpublishRpcMethod - unregister RPC method from RPC server process and LS.

func OpenRpcConn(rpcname string) resDesc

OpenRpcConn - Open client connection to a Named RPC method.

func CloseRpcConn(rpcClient resDesc) error

CloseRpcConn - Close client RPC connection opened in OpenRpcConn().

func (client *resDesc) RpcCall(args interface{}, reply interface{}) error

RpcCall - synchronous call to remote RPC method.

func (client *resDesc) RpcGo(args interface{}, reply interface{}) *rpcCall

RpcGo - asynchronous call to remote RPC method.

func RpcArgs(args interface{}, dataptr interface{}) []byte

RpcArgs - converts incoming JSON []byte slice to user defined data. Used in remote method. See example II.

func RpcReply(ret interface{}) []byte

RpcReply - Convert user process return data structure to JSON []byte slice. Used in remote method. See example II.

Test Example

See src/mbx_tst/mbx.go .
To run the test in Linux environment:

$ cd src/mbx_tst
$ ./test.sh

To run the test in Windows environment:

> cd src/mbx_tst
> test.bat

This script will start Locations Service and run a number of test programs.