If websocket messages arrive in order, why does 'sequence number' is needed? - sockets

I heard that websocket messages are received in order, because websocket runs over TCP.
Then what is the purpose of 'sequence number'?
This is the explanation of sequence number in websocket.
But I'm wondering why does that sequence number is needed, if we have a 'in-order' received message.

The sequence number allows you to map your requests to responses even if the responses don't come in the order you make them.
HTTP and other relevant protocols support pipelining. Also there is no need for the request responses to be sent back to you in any specific order. Each one may be processed according to its individual cost or dispatched across a server farm and reassembled in an order that is not predetermined. Either way, if they are out of order you will need a key to map the response back to your request.

Related

Is there any promise that Dart Stream API must preserve the order of elements?

I have a question about the contract on Stream API.
More specifically, I'm wondering why Stream.asyncMap is implemented not to break the order of elements in the stream.[1]
I guess there can be some cases where the order of elements is not kept on asyncMap.
For example, if I pass an asynchronous function with HTTP communication to a server where the response latency has large variance, the events might happen in order of (1) HTTP req is sent for the 1st element (2) HTTP req is sent for the 2nd element (3) HTTP res is received for the 2nd element and sent to the downstream (4) HTTP res is received for the 1st element and sent to the downstream. In this case, the output stream will be ordered as [res2, res1] for the shortest latency as a whole.
However, in fact, the implementation is intend this order: (1) HTTP req is sent for the 1st element and pause the subscription (2) HTTP res is received, it is added to the downstream, and the subscription is resumed (3) HTTP req is sent for the 2nd element and (4) HTTP res is received and sent to the downstream.
So I want to know the intention of this implementation. I guess there might be an official contract that Stream API must not break the order, but I'm not sure.
Any insight will be helpful, thanks!

Matching REST requests with responses in asynchronous server

I have a Boost Asio/Beast based server that maintains a HTTP connection (keep-alive) to a REST service. My server listens for various commands, e.g. "send", "cancel", "ping". Requests are queued accordingly, and processed in an asynchronous manner.
When I read a response, I do not know how to match it with the corresponding request. For example, both "cancel" and "ping" may respond with empty strings, and as far as I know responses are not guaranteed to be processed in the order of requests.
Is there a way to match the two?
Response ordering is guaranteed in HTTP/1.1.

Sending response in a Pub-Sub architecture

At the moment I have a single AWS EC2 instance which handles all incoming http client requests. It analyses each request and then decides which back end worker server should handle the request and then makes a http call to the chosen server. The back end server then responds when it has processed the request. The front end server will then respond to the client. The front end server is effectively a load balancer.
I now want to go to a Pub-Sub architecture instead of the front end server pushing the requests to the back end instances. The front end server will do some basic processing and then simply put the request into an SNS queue and the logic of which back end server should handle the request is left to the back end servers themselves.
My question is with this model what is the best way to have the back end servers notify the front end server that they have processed the request? Previously they just replied to the http request the front end server sent but now there is no direct request, just an item of work being published to a queue and a back end instance picking it off the queue.
Pubsub architectures are not well suited to responses/acknowledgements. Their fire-and-forget broadcasting pattern decouples publishers and the subscribers: a publisher does not know if or how many subscribers there are, and the subscribers do no know which publisher generated a message. Also, it can be difficult to guarantee sequence of responses, they won't necessarily match the sequence of messages due to the nature of network comms and handling of messages can take different amounts of time etc. So each message that needs to be acknowledge needs a unique ID that the subscriber can include in its response so the publisher can match a response with the message sent. For example:
publisher sends message "new event" and provides a UUID for the
event
many subscribers get the message; some may be the handlers for
the request, but others might be observers, loggers, analytics, etc
if only one subscriber handles the message (e.g. the first
subscriber to get a key from somewhere), that subscriber generates a
message "new event handled" and provides a UUID
the original
publisher, as well as any number of other subscribers, may get that
message;
the original publisher sees the ID is
in its cache as an unconfirmed message, and now marks it as
confirmed
if a certain amount of time passes without receiving a
confirmation with given ID, the original publisher republishes the
original message, with a new ID, and removes the old ID from cache.
In step 3, if many subscribers handled the message instead of just one, then it
less obvious how the original publisher should handle "responses": how does it
know how many subscribers handle the message, some could be down or
too busy to respond, or some may be in the process of responding by the time
the original publisher determines that "not enough handlers have
responded".
Publish-subscribe architectures should be designed to not request any response, but instead to check for some condition that should have happened as a result of the command being handled, such as a thumbnail having gotten generated (it can assume as a result of a handler of the message).

How to respond with multiple messages in a sync (two-way) camel route?

I'd like to model an Apache Camel route that accepts tcp requests containing xml messages.
Each message may result in a multitude of responses which should be sent back on the incoming socket. I've played around with the camel-netty component in sync mode which works for single messages.
But is it possible to send back multiple messages on the socket? Basically a split before the return.
from(String.format("netty:tcp://0.0.0.0:%s?sync=true&decoders=#length-decoder,#string-decoder&encoders=#string-encoder,#length-encoder", INBOUND_PORT))
.id("my-mock")
.unmarshal(jaxbDataFormat)
.process(exchange -> {
List<String> responses = service.accept(exchange.getIn().getBody(MyXmlRootElement.class));
exchange.getOut().setBody(responses);
})
.split().body() //Split is not doing what it should. Should become multiple messages, and each should be returned with a delay
.delay(2000);
My messages are length-encoded containing an integer at first 4 bytes specifying the length of each individual message.
In my case the exception is IllegalArgument, stating that the endpoint does not support ArrayList as the payload.
Caused by: [java.lang.IllegalArgumentException - unsupported message type: class java.util.ArrayList]
at org.apache.camel.component.netty.handlers.ServerResponseFutureListener.operationComplete(ServerResponseFutureListener.java:53) ~[camel-netty-2.16.0.jar:2.16.0]
at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:409) [netty-3.10.4.Final.jar:na]
at org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:395) [netty-3.10.4.Final.jar:na]
Cheers.
That is not how its designed, the sync option on netty is for sending one response message when the route ends.
I have designed this as well for single messages and that works. For multiple response messages, you could try to aggregate them as one and send that back to the client. Assuming off course aggregation is possible in your case.

Sending And Receiving Sockets (TCP/IP)

I know that it is possible that multiple packets would be stacked to the buffer to be read from and that a long packet might require a loop of multiple send attempts to be fully sent. But I have a question about packaging in these cases:
If I call recv (or any alternative (low-level) function) when there are multiple packets awaiting to be read, would it return them all stacked into my buffer or only one of them (or part of the first one if my buffer is insufficient)?
If I send a long packet which requires multiple iterations to be sent fully, does it count as a single packet or multiple packets? It's basically a question whether it marks that the package sent is not full?
These questions came to my mind when I thought about web sockets packaging. Special characters are used to mark the beginning and end of a packet which sorta leads to a conclusion that it's not possible to separate multiple packages.
P.S. All the questions are about TCP/IP but you are welcomed to share information (answers) about UDP as well.
TCP sockets are stream based. The order is guaranteed but the number of bytes you receive with each recv/read could be any chunk of the pending bytes from the sender. You can layer a message based transport on top of TCP by adding framing information to indicate the way that the payload should be chunked into messages. This is what WebSockets does. Each WebSocket message/frame starts with at least 2 bytes of header information which contains the length of the payload to follow. This allows the receiver to wait for and re-assemble complete messages.
For example, libraries/interfaces that implement the standard Websocket API or a similar API (such as a browser), the onmessage event will fire once for each message received and the data attribute of the event will contain the entire message.
Note that in the older Hixie version of WebSockets, each frame was started with '\x00' and terminated with '\xff'. The current standardized IETF 6455 (HyBi) version of the protocol uses the header information that contains the length which allows much easier processing of the frames (but note that both the old and new are still message based and have basically the same API).
TCP connection provides for stream of bytes, so treat it as such. No application message boundaries are preserved - one send can correspond to multiple receives and the other way around. You need loops on both sides.
UDP, on the other hand, is datagram (i.e. message) based. Here one read will always dequeue single datagram (unless you mess with low-level flags on the socket). Event if your application buffer is smaller then the pending datagram and you read only a part of it, the rest of it is lost. The way around it is to limit the size of datagrams you send to something bellow the normal MTU of 1500 (less IP and UDP headers, so actually 1472).