REST for comms (GOTO 2015 talk)

319 views
Skip to first unread message

Ziad Hatahet

unread,
Aug 17, 2017, 1:19:58 AM8/17/17
to mechanica...@googlegroups.com
Martin mentions at 30:22 during his talk[1] that REST, while still better than RPC, still causes coupling between communicating actors as opposed to messaging.

My question is: what's preventing REST calls from being wrapped in a future or higher level messaging construct (e.g. Akka actor messages) such that communication is decoupled because it becomes asynchronous?


[1] Beginning of discussion at https://www.youtube.com/watch?v=oxjT7veKi9c&t=1805

Thanks,

--
Ziad

Todd Montgomery

unread,
Aug 17, 2017, 1:25:14 PM8/17/17
to mechanical-sympathy
REST and RPC have good uses. But they are not a panacea.

REST has implicit coupling because each HTTP request must have a corresponding HTTP response. Think of this as mandatory coupling from the protocol perspective. This implies that management between a request and its response must be done. (For retry, error, etc.). Whether you wrap that in a future or not is somewhat cosmetic. Web Services and the protocols attached to them are designed to try, as best they can, to decouple requests/processing/response.... but can't separate request and response from the HTTP perspective.

From a higher perspective, HTTP can be made to look asynchronous from the request, response, and processing angles.... at the application level. However, most of the time, this is rarely done. Or done well.

To allow full async communication, the basic communication block must be simplex (1-way) and not have response dependency at the application nor protocol level.

This may seem that we are bashing on REST... and we are... somewhat. Mostly, though, we are bashing how REST is used. More like a hammer and everything is a nail. While in many cases, not nearly everything is a nail. And the hammer leaves a lot of "collateral damage" in the form of coupling and dependency that is unnecessary. For example, an extremely common problem with some systems using REST is throughput being restricted by RTT due to response coupling (application or protocol).

--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Kirk Pepperdine

unread,
Aug 17, 2017, 6:09:03 PM8/17/17
to mechanica...@googlegroups.com
It’s very common for people to add layers of abstraction in order to “decouple” components not realizing that all they are doing is hiding the coupling making it more difficult when things have to change. The phenomenon you’re trying to ignore is known as leaky abstraction in that there are some details you simply cannot abstract away and those that you cannot abstract away will leak into your abstraction layer. Anytime you offer a service you are implicitly defining a contract or API for those that want to use that service. Part of that contract will be how you present data to that service. You can’t abstract that detail away meaning that dependency though hidden, still exists. It leaks.

There is a rule that I’ve always though to be very sensible and that is, “the server owns the wire”. In other words, any service you offer should come with an API that clients can use w.r.t. the communication protocol you should decide to use. In this way you get to manage as many of the dependencies as is possible. That you are using REST should not be exposed to the users of the service. I know this isn’t a popular idea but… If you expose the communication protocol than it’s much more difficult to change the underlying communication protocol. If you “own the wire”, very easy to change things.

As for messaging… it also causes implicit couplings between the client and the service provider. However, messaging implies the server owns the wire meaning you can easily change the communication protocol. I don’t see it as being any different than REST in that regards. Same with RPC. With traditional RPC, the frameworks will generate a client library which in turns implies you own the wire and thus have more control over the communication protocol.

Kind regards,
Kirk

--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-symp...@googlegroups.com.

Ziad Hatahet

unread,
Aug 17, 2017, 8:49:20 PM8/17/17
to mechanica...@googlegroups.com
Hey Todd! I didn't know you frequented this list, I really appreciate the reply.
Great talk by the way.


> To allow full async communication, the basic communication block must be simplex
> (1-way) and not have response dependency at the application nor protocol level.

Something similar to UDP then? How would we deal with reliability in that case?
Otherwise, if you mean for levels higher up in the stack, how do we deal with
error situations if we should not have a response dependency?

A project I worked on previously used actors deployed in a pipeline manner,
where each actor would receive data from the previous actor, process the data,
then forward them on to the following actor. The main information flow at the
data processing level was one-way; however, we still had to implement flow
control with back-pressure awareness, which made the "control plane" part of the
protocol be two-way. How would this fit into what you mentioned?


> For example, an extremely common problem with some systems using REST is
> throughput being restricted by RTT due to response coupling (application or
> protocol).

If I understand this correctly, what you're saying is that we won't be able to
batch requests for example due to this tight coupling between requests and
responses, among potentially other performance improvements as mentioned in the
talk.

Todd Montgomery

unread,
Aug 18, 2017, 11:37:06 AM8/18/17
to mechanical-sympathy
On Thu, Aug 17, 2017 at 5:48 PM, Ziad Hatahet <hat...@gmail.com> wrote:
Hey Todd! I didn't know you frequented this list, I really appreciate the reply.
Great talk by the way.

Thanks! Glad you liked it!
 

> To allow full async communication, the basic communication block must be simplex
> (1-way) and not have response dependency at the application nor protocol level.

Something similar to UDP then? How would we deal with reliability in that case?
Otherwise, if you mean for levels higher up in the stack, how do we deal with
error situations if we should not have a response dependency?

TCP is fine for most situations demanding simplex. ACKs act as both reliability and flow/congestion control.
While ACKs couple, what it provides is extremely useful and TCP itself doesn't introduce any unnecessary coupling
(in most cases) by requiring ACKs for progress. It's a very good tradeoff.

So, UDP may not be necessary. However, when it is, adding reliability with negative acknowledgements
(NAKs aka ARQ = automated repeat request) is a lot simpler than you might think.

Aeron, for example, provides reliability and adds flow (and optionally congestion) control as well on top of UDP.
And can still go very very fast.

But flow control, for example, is quite different than a response dependency that something like
HTTP demands. HTTP responses are a very poor flow control signal. In fact, HTTP/1.1, with a lack of HTTP pipelining,
means that no effective muxing can be done. This introduces head-of-line blocking and limits throughput and
introduces unbounded latency. HTTP/2 is better in this regard, but responses alone are not enough. Which
is why HTTP/2 uses window updates and per stream flow control. Only once all of that is in use does the benefits
of muxing start to show up.

Handling errors in a simplex manner is quite easy. NAK-style retransmission handles a multitude of
error cases and is, in general, more flexible than positive ACKs saying "200 OK" (for example).

Also, in most systems treating errors as messages is a lot simpler of a technique. (A NAK-style
retransmission is a message).
 

A project I worked on previously used actors deployed in a pipeline manner,
where each actor would receive data from the previous actor, process the data,
then forward them on to the following actor. The main information flow at the
data processing level was one-way; however, we still had to implement flow
control with back-pressure awareness, which made the "control plane" part of the
protocol be two-way. How would this fit into what you mentioned?

Indeed. Quite easily. Pipelines are extremely effective. For flow control, in that style of
system, each stage can (and should) have it's own back pressure and push back upstream. End-to-end
flow control is only needed if the last stage/end processing needs to push back and induce a rate that is
slower than the individual stages flow control back pressure. In a well designed pipeline, this is
almost never the persistent (always happening) case, though.

BTW, per stage flow control is a pre-req for end-to-end flow control in a stable system as they
both address different concerns. Without per stage flow control, end-to-end loss MUST be handled
because the only option is to drop data in the middle to handle the case of flow control being overrun.
 


> For example, an extremely common problem with some systems using REST is
> throughput being restricted by RTT due to response coupling (application or
> protocol).

If I understand this correctly, what you're saying is that we won't be able to
batch requests for example due to this tight coupling between requests and
responses, among potentially other performance improvements as mentioned in the
talk.

Indeed. What normally happens in HTTP/1.1 (and most systems using REST still use HTTP/1.1) is that a client sends a single request and waits for the response.
This limits throughput to the RTT. 

Next step is someone says, lets have N requests outstanding at a time. So,
correlation of responses is introduced in some way. Usually very brittle and usually buggy. And N is a static number.
Throughput goes up somewhat, but lags where it could be. One problem is that N is normally static and it's hard to
determine what N should be. Maybe 5? Maybe 6? Let's try 7..... or 8?

Most systems stop there as it is tough to know how to make things better. But notice that throughput is limited to N * RTT
still. Better, but still limited by RTT.

One trick is to make N dynamic. Which is emulating flow control. But in this case flow control couples requests and responses.

About this time, most systems also start to realize that HTTP/1.1 can not multiplex requests/responses and that HTTP pipelining is
hard to do well.

The trick a lot of times is to decouple requests from responses (treat each as separate messages in a truly async fashion) and decouple 
flow control and flow control each (request and response) separately instead of coupling them to one another.

Edward Sargisson

unread,
Aug 18, 2017, 7:55:06 PM8/18/17
to mechanical-sympathy
I'm finding this discussion an extremely good summary.

For clarity, is HTTP/2 an example of dynamic N and/or properly pipelined? (I may have the definitions of these two confused)

In other words, if you use HTTP/2 do you manually break the RTT bounds?

Cheers,
Edward

Todd Montgomery

unread,
Aug 18, 2017, 8:04:30 PM8/18/17
to mechanical-sympathy
Hi Edward.

h2 doesn't mandate a dynamic or static N. But it does allow multiple outstanding requests and responses as well as a form of pipelining. And per
stream flow control. However, the implementation must also support such.

So, yes, the protocol has the ability to break the RTT bounds on throughput.

HTTP/1.1 can also. But to do so starts to be much less than standard.

REST over h2 is a great place to be. But, if you are desiring something simple, h2 and REST mapping on it is a lot more complex than you might want.

To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscribe...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Ziad Hatahet

unread,
Sep 4, 2017, 6:35:07 AM9/4/17
to mechanica...@googlegroups.com
Thank you so much Todd. That was very enlightening :-)

I'll watch the talk on Aeron you gave at the same conference.

Cheers

Greg Young

unread,
Sep 4, 2017, 7:06:05 AM9/4/17
to mechanica...@googlegroups.com
This is slightly changed in http 2.0 (unsolicited response)

To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsubscribe...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "mechanical-sympathy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mechanical-sympathy+unsub...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Studying for the Turing test
Reply all
Reply to author
Forward
0 new messages