ETCD Client Watch Event Load Balancer - grpc

Is there an already made solution that allows for the load balancing of ETCD Watch events?
The requested solution in question is as follows:
"Client A" establishes a watch stream for key /app/status
"Client B" establishes a watch stream for key /app/status
"Client C" establishes a watch stream for key /app/status
In ETCD the key /app/status is changed from a separate client
The "Load Balancer" ensures that only "Client B" receives this change event
In ETCD the key /app/status is changed again from a separate client
The "Load Balancer" ensures that only "Client C" receives this change event
In ETCD the key /app/status is changed again from a separate client
The "Load Balancer" ensures that only "Client A" receives this change event
As can be seen in the example the load balancer is performing a round robin load balance on the returning event.
I have looked at the GRPC Proxy in ETCD, this combines watch requests to the ETCD server which is good but broadcasts the event back to the clients meaning that all clients receive the event. I couldn't see any option that allows me to change the broadcast behavior of the client.
Is this request breaking a fundamental part of Watch streams in the ETCD architecture? Should I be using something different to ETCD for this functionality?

Related

How are Server-Sent Events supposed to be used in a "update list" scenario?

What I want to achieve is the following:
There is a list of things and the server wants to notify the client about changes to that list.
Which of the following setups are recommended and why:
I send an SSE request from the client to the server and the server sends updates of the list in an event. The server doesn't close the connection, it is closed when client leaves the page the list is on.
I send an SSE request from the client to server. The server sends an event when the list is updated, then closed the connection. The client then (after processing the event) sends a new request to the server, waiting for another event from the server.

How webpush work in TCP/IP network layers

Please explain to me how webpush work in TCP/IP network layers (especially layer 4-5).
I understand that HTTP is stateless protocol:
the protocol is opening TCP / layer 4 connection,
'state' is 'made to work' with cookie/session,
then client send HTTP request (plaintext/compressed "HTTP/1.1 /url/here ... Content-Length: ..."),
then server respond with HTTP request (plaintext/compressed "200 OK ... ..."),
Therefore it's understandable that for a user behind NAT to be able to view webpage of a remote host (because the user behind NAT is the one initiating the connection); but the webserver cannot initiate TCP connection with the client (browser process).
However there are some exceptions like 'websocket' where client (browser) initiate a connection, then leave it open (elevate to just TCP, not HTTP anymore). In this architecture, webserver may send / initiate sending message to client (for example "you have new chat message" notification).
What I don't understand is the new term 'webpush'.
I observed that it can send notification from server to client/browser (from user, it 'feels' like the server is the one initiating the connection)
webpush can send notification anytime, even when browser is closed / not opened yet (as when the device was just freshly turned on), or when it's just connected to internet
How does it work? How do they accomplish this? Previously I think that:
either a javascript in a page is continously (ex: 5 second interval) checking if there's a new notification in server,
or a javascript initiate a websocket (browser initiate/open TCP connection) and keep it alive, when server need to send something, it's sent from webserver to client/browser through this connection
Is this correct? Or am I missing something? Since both of my guess above won't work behind NAT'd network
Is Firebase web notification also this kind of webpush?
I have searched the internet for explanation on what make it work on client side, but there seems only explanation on 'how to send webpush', 'how to market your product with webpush', those articles only explain the server side (communication of app server with push service server) or articles about marketing.
Also, I'm interested in understanding what application layer protocol they're running on (as in what text/binary data the client/server send to each other), if it's not HTTP
Web Push works because there is a persistent connection between the browser (e.g. Chrome) and the browser push service (e.g. FCM).
When your application server needs to send a notification to a browser, it cannot reach the browser directly with a connection, instead it contacts the browser push service (e.g. FCM for Chrome) and then it's the browser push service that delivers the notification to the user browser.
This is possible because the browser constantly tries to keep an open connection with the server (e.g. FCM for Chrome). This means that there isn't any problem for NAT, since it's the clients that starts the connection. Also consider that any TCP connection is bi-directional: so any side of the connection can start sending data at any time. Don't confuse higher level protocols like HTTP with a normal TCP connection.
If you want more details I have written this article that explains in simple words how Web Push works. You can also read the standards: Push API and IETF Web Push in particular.
Note: Firebase (FCM) is two different things, even if that is not clear from the documentation. It is both the browser push service required to deliver notifications to Chrome (like Mozilla autopush for Firefox, Windows Push Notification Services for Edge and Apple Push Notification service for Safari), but it is also a proprietary service with additional features to send notifications to any browser (like Pushpad, Onesignal and many others).

Does the communication channel breaks in between client and server if we introduce a load balancer in SignalR?

I am new to SignalR and I have a question on SignalR communication when we introduce a load balancer.
Lets assume we want to execute a void method on server side which receives some data as a parameter from client. Server takes that data and processes further. Lets say after processing for a while, it identifies that it has to send the notification back to client.
Case 1(Between client and server): Client calls void method on server side(Hub) by passing some data. Connection gets disconnected. Server processes the client data further. When it identifies that it has to push the notification back to client, it recreates the connection and pushes back the data to client.
Case 2(Between client and server with load balancer in between): How does the above scenario(Case 1) work here?. When server sends the push notification back to load balancer after processing client data, how does it know to which client it has to send the notification back?
You should read the scaleout docs. Short version: messages get sent to all servers, so if the client reconnects (it's not the server that establishes the connection!) before the connection times out , it will get the message.
Quote from the docs:
The cursor mechanism works even if a client is routed to a different
server on reconnect. The backplane is aware of all the servers, and it
doesn’t matter which server a client connects to.

Clustering comet backend

Our problem: we have more than 300 000 online clients to application (50 000 to one node). Because we use load balancer we don't now where (which nginx instance) alive connection to client. So we need pub message to all nodes.
How we can get linear scalability?
Current functionality:
Comet(for us comet is required) clients (mobile/web browsers) and server (java) with pub-sub functionality.
Client can send notifications to other (single) client;
Server can send notifications to single client or group of clents;
Clients recieve information about active clients (by group) from nginx+memcached
Now we use: nginx + https://github.com/wandenberg/nginx-push-stream-module + memcached.
Client before set up on comet channel send request to server: "I am alive and my commet channel id ...". Each 10 min client reopen pipeline, but register as alive on server only once (it's other problem).
I think we can write some logic with Lua on nginx(+redis or memcached). And each client request for reopen pipeline update information in redis (+add additional information about nginx instance ip which bind connection).
But may be exist other variants or practice for scalability comet functionality?

HTTP and Sessions

I just went through the specification of http 1.1 at http://www.w3.org/Protocols/rfc2616/rfc2616.html and came across a section about connections http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8 that says
" A significant difference between HTTP/1.1 and earlier versions of HTTP is that persistent connections are the default behavior of any HTTP connection. That is, unless otherwise indicated, the client SHOULD assume that the server will maintain a persistent connection, even after error responses from the server.
Persistent connections provide a mechanism by which a client and a server can signal the close of a TCP connection. This signaling takes place using the Connection header field (section 14.10). Once a close has been signaled, the client MUST NOT send any more requests on that connection. "
Then I also went through a section on http state management at https://www.rfc-editor.org/rfc/rfc2965 that says in its section 2 that
"Currently, HTTP servers respond to each client request without relating that request to previous or subsequent requests;"
A section about the need to have persistent connections in the RFC 2616 also said that prior to persistent connections every time a client wished to fetch a url it had to establish a new TCP connection for each and every new request.
Now my question is, if we have persistent connections in http/1.1 then as mentioned above a client does not need to make a new connection for every new request. It can send multiple requests over the same connection. So if the server knows that every subsequent request is coming over the same connection, would it not be obvious that the request is from the same client? And hence would this just not suffice to maintain the state and would this just nit be enough for the server to understand that the request was from the same client ? In this case then why is a separate state management mechanism required at all ?
Basically, yes, it would make sense, but HTTP persistent connections are used to eliminate administrative TCP/IP overhead of connection handling (e.g. connect/disconnect/reconnect, etc.). It is not meant to say anything about the state of the data moving across the connection, which is what you're talking about.
No. For instance, there might an intermediate (such as a proxy or a reverse proxy) in the request path that aggregates requests from multiple TCP connections.
See http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p1-messaging-21.html#intermediaries.

Resources