You are viewing a plain text version of this content. The canonical link for it is here.
Posted to proton@qpid.apache.org by aconway <ac...@redhat.com> on 2015/10/23 00:19:51 UTC

The Go electron API: a tale of two brokers.

The Go binding for proton provides 2 alternate APIs, `proton` is an
exact analogue of the event-driven proton C API and `electron` which is
a more go-oriented, procedural API. The differences were motivated by
the concurrency features of the Go language but there may be lessons to
learn for other languages. Take a look at 

https://github.com/alanconway/qpid-proton/tree/master/examples/go


## A tale of two brokers

The `proton` and `electron` packages provide two alternate APIs for
AMQP applications.  See [the proton Go README](https://github.com/apach
e/qpid-proton/blob/master/proton
-c/bindings/go/src/qpid.apache.org/README.md) for a discussion of why
there are two APIs.

The examples `proton/broker.go` and `electron/broker.go` both implement
the same simple broker-like functionality using each of the two APIs.
They both handle multiple connections concurrently and store messages
on bounded queues implemented by Go channels.

However the `electron/broker` is less than half as long as the
`proton/broker` illustrating why it is better suited for most Go
applications.

`proton/broker` must explicitly handle proton events, which are
processed in a single goroutine per connection since proton is not
concurrent safe. Each connection uses channels to exchange messages
between the event-handling goroutine and the shared queues that are
accessible to all connections. Sending messages is particularly tricky
since we must monitor the queue for available messages and the sending
link for available credit in order to send messages.


`electron/broker` takes advantage of the `electron` package, which
hides all the event handling and passing of messages between goroutines
beind behind straightforward interfaces for sending and receiving
messages. The electron broker can implement links as simple goroutines
that loop popping messages from a queue and sending them or receiving
messages and pushing them to a queue.



Re: The Go electron API: a tale of two brokers.

Posted by aconway <ac...@redhat.com>.
An interesting lesson I learned building these brokers, this is more
about the Go language than the differences between the proton and
electron APIs:

Go channels encourages proper flow control: they cannot be unbounded
and sending to a full channel blocks until a value is removed.

Both Go brokers use fixed-size bounded channels as simple queues, and
as receive buffers for receiving links (in the electron API the channel
is hidden by the Receiver interface but it is there.) Both use
goroutines to transfer messages from buffer to queue.

When a queue is full, goroutines sending to it are blocked. Receivers
can buffer messages but only up to a fixed limit, at which point they
stop issuing credit. So once the queues are full, clients sending
messages are also blocked, the broker will not grow without limit. As
soon as a message is taken off a queue, one of the receiver goroutines
can unblock, move a message from buffer to queue, and issue credit to
get the whole thing moving again.
 
Complete end-to-end flow control across the queue (which was a big
effort to implement in qpidd c++ for example) falls out in a trivial
broker demo as a natural consequence of using channels and goroutines.

On Thu, 2015-10-22 at 18:19 -0400, aconway wrote:
> The Go binding for proton provides 2 alternate APIs, `proton` is an
> exact analogue of the event-driven proton C API and `electron` which
> is
> a more go-oriented, procedural API. The differences were motivated by
> the concurrency features of the Go language but there may be lessons
> to
> learn for other languages. Take a look at 
> 
> https://github.com/alanconway/qpid-proton/tree/master/examples/go
> 
> 
> ## A tale of two brokers
> 
> The `proton` and `electron` packages provide two alternate APIs for
> AMQP applications.  See [the proton Go README](
> https://github.com/apach
> e/qpid-proton/blob/master/proton
> -c/bindings/go/src/qpid.apache.org/README.md) for a discussion of why
> there are two APIs.
> 
> The examples `proton/broker.go` and `electron/broker.go` both
> implement
> the same simple broker-like functionality using each of the two APIs.
> They both handle multiple connections concurrently and store messages
> on bounded queues implemented by Go channels.
> 
> However the `electron/broker` is less than half as long as the
> `proton/broker` illustrating why it is better suited for most Go
> applications.
> 
> `proton/broker` must explicitly handle proton events, which are
> processed in a single goroutine per connection since proton is not
> concurrent safe. Each connection uses channels to exchange messages
> between the event-handling goroutine and the shared queues that are
> accessible to all connections. Sending messages is particularly
> tricky
> since we must monitor the queue for available messages and the
> sending
> link for available credit in order to send messages.
> 
> 
> `electron/broker` takes advantage of the `electron` package, which
> hides all the event handling and passing of messages between
> goroutines
> beind behind straightforward interfaces for sending and receiving
> messages. The electron broker can implement links as simple
> goroutines
> that loop popping messages from a queue and sending them or receiving
> messages and pushing them to a queue.
> 

Re: The Go electron API: a tale of two brokers.

Posted by aconway <ac...@redhat.com>.
An interesting lesson I learned building these brokers, this is more
about the Go language than the differences between the proton and
electron APIs:

Go channels encourages proper flow control: they cannot be unbounded
and sending to a full channel blocks until a value is removed.

Both Go brokers use fixed-size bounded channels as simple queues, and
as receive buffers for receiving links (in the electron API the channel
is hidden by the Receiver interface but it is there.) Both use
goroutines to transfer messages from buffer to queue.

When a queue is full, goroutines sending to it are blocked. Receivers
can buffer messages but only up to a fixed limit, at which point they
stop issuing credit. So once the queues are full, clients sending
messages are also blocked, the broker will not grow without limit. As
soon as a message is taken off a queue, one of the receiver goroutines
can unblock, move a message from buffer to queue, and issue credit to
get the whole thing moving again.
 
Complete end-to-end flow control across the queue (which was a big
effort to implement in qpidd c++ for example) falls out in a trivial
broker demo as a natural consequence of using channels and goroutines.

On Thu, 2015-10-22 at 18:19 -0400, aconway wrote:
> The Go binding for proton provides 2 alternate APIs, `proton` is an
> exact analogue of the event-driven proton C API and `electron` which
> is
> a more go-oriented, procedural API. The differences were motivated by
> the concurrency features of the Go language but there may be lessons
> to
> learn for other languages. Take a look at 
> 
> https://github.com/alanconway/qpid-proton/tree/master/examples/go
> 
> 
> ## A tale of two brokers
> 
> The `proton` and `electron` packages provide two alternate APIs for
> AMQP applications.  See [the proton Go README](
> https://github.com/apach
> e/qpid-proton/blob/master/proton
> -c/bindings/go/src/qpid.apache.org/README.md) for a discussion of why
> there are two APIs.
> 
> The examples `proton/broker.go` and `electron/broker.go` both
> implement
> the same simple broker-like functionality using each of the two APIs.
> They both handle multiple connections concurrently and store messages
> on bounded queues implemented by Go channels.
> 
> However the `electron/broker` is less than half as long as the
> `proton/broker` illustrating why it is better suited for most Go
> applications.
> 
> `proton/broker` must explicitly handle proton events, which are
> processed in a single goroutine per connection since proton is not
> concurrent safe. Each connection uses channels to exchange messages
> between the event-handling goroutine and the shared queues that are
> accessible to all connections. Sending messages is particularly
> tricky
> since we must monitor the queue for available messages and the
> sending
> link for available credit in order to send messages.
> 
> 
> `electron/broker` takes advantage of the `electron` package, which
> hides all the event handling and passing of messages between
> goroutines
> beind behind straightforward interfaces for sending and receiving
> messages. The electron broker can implement links as simple
> goroutines
> that loop popping messages from a queue and sending them or receiving
> messages and pushing them to a queue.
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org