gRPC Distributed Servers - Keeping Packet Order - grpc

I'm trying out gRPC as a solution to a problem and im wondering if its possible to do that, i have not found anything regarding this.
Ill exemplify the problem
Let's say i have a distributed server A of 100 nodes.
Those servers are going to call another server B, which is a single node, using gRPC calls. Each node has a pool of connections open to server B.
The goal is to make sure server B receives all requests in order. Since latency can vary, if two nodes of server A sends requests almost at the same time, it would be possible to receive those requests in an incorrect order ?
Would apreciate any help. Thanks

inter stream order is not guaranteed in http2 layer. your best bet is client generates a sequence number (this is yet another very hard problem), so you can handle it in order on the server side (B).
Note that telling order of request itself is very hard unless you have an atomic clock.
this problem usually means you are trying solve the actual problem in wrong way. with some legacy code this can be unavoidable, but better to fix underlying issue rather than fix it in hacky way or something impossible.

Related

NamedPipeClientStream - Notifications if server has disconnected

I have a question and I couldn't find any answer here.
I am using the NamedPipeClientStream/NamedPipeServerStream classes for bidirectional IPC communication in a .NET 5.0/.NET Framework 4.8 environment and it works fine, however I need to have a way of letting the client (immediately) know if the server is not running anymore and I am not sure what is the best way to achieve this.
Of course I can try on the client side to call Connect with a timeout every 3 seconds for example and if I get a TimeoutException, then it means the server is not available, however as far I as have read, doing this (for example with a timer and/or a background thread) is not very efficient. Are there better ways to do this (and still use named pipes)? Can someone point me in another (better) direction?
I had it solved before with WCF, however as .NET Core doesn't support it, it is not a solution anymore.
Thank you very much.
BR,
M.
You could do a twofold approach where if a server shuts down nicely you send a 'i am shutting down' message to the client. And also have the server send small heartbeat messages once per second to clients. This way clients can check if the last heartbeat is stale or the server has shutdown whenever they need.
Looking for a WCF replacement myself and came across your post ;-)

Port seems to be shared between to separate grpc channels in same process

My questions concerns gRPC clients using the C core, specifically C++
I've been debugging one of our servers, and I've noticed a certain two-client flow worked when the clients were launched from separate processes (two separate console windows) but not from within an automated test case (which runs within a single process). The flow in question involves two "clients" (channels, basically) which are alive at the same time and concurrently issuing requests to the same server
Digging further, I discovered that in the working flow the server received requests from two different ip:port combinations: 127.0.0.1:xxxx and 127.0.0.1:yyyy. In the failing scenario however, both requests come from the same ip:port.
I create a separate channel for every client, so this behavior confused me. I have a couple of questions
Does gRPC share ports between channels in the same process like this? If not, then I have to imagine there's a bug in my code
If yes to (1), is there any way to avoid this port reuse?
I do see the "grpc.so_reuseport" option in the channel's metadata, and note that it is enabled by default. This seems more related to servers than clients (though perhaps I'm making an arbitrary distinction), but I'll disable it and try things out
EDIT: The so_reuseport option doesn't do anything, but I am on Windows so I should have expected that anyways :/ I also found a related question without any answers here
EDIT 2: The discussion on this question seems promising. Will try it out and report back
This is mentioned/explained in the question I link in edit 2, but the answer is to use
auto metadata = grpc::ChannelArguments();
metadata.SetInt(GRPC_ARG_USE_LOCAL_SUBCHANNEL_POOL, 1);
and pass it to grpc::CreateCustomChannel

Is it realistic for a dedicated server to send out many requests per second?

TL;DR
Is it appropriate for a (dedicated) web server to be sending many requests out to other servers every second (naturally with permission from said server)?
I'm asking this purely to save myself spending a long time implementing an idea that won't work, as I hope that people will have some more insight into this than me.
I'm developing a solution which will allow clients to monitor the status of their server. I need to constantly (24/7) obtain more recent logs from these servers. Unfortunately, I am limited to getting the last 150 entries to their logs. This means that for busy clients I will need to poll their servers more.
I'm trying to make my solution scalable so that if it gets a number of customers, I won't need to concern myself with rewriting it, so my benchmark is 1000 clients, as I think this is a realistic upper limit.
If I have 1000 clients, and I need to poll their servers every, let's give it a number, two minutes, I'm going to be sending requests off to more than 8 servers every second. The returned result will be on average about 15,000 characters, however it could go more or less.
Bearing in mind this server will also need to cope with clients visiting it to see their server information, and thus will need to be lag-free.
Some optimisations I've been considering, which I would probably need to implement relatively early on:
Only asking for 50 log items. If we find one already stored (They are returned in chronological order), we can terminate. If not, we throw out another request for the other 100. This should cut down traffic by around 3/5ths.
Detecting which servers get more traffic and requesting their logs less commonly (i.e. if a server only gets 10 logged events every hour, we don't want to keep asking for 150 every few minutes)
I'm basically asking if sending out this many requests per second is considered a bad thing and whether my future host might start asking questions or trying to throttle my server. I'm aiming to go shared for the first few customers, then if it gets popular enough, move to a dedicated server.
I know this has a slight degree of opinion enabled, so I fear that it might be a candidate for closure, but I do feel that there is a definite degree of factuality required in the answer that should make it an okay question.
I'm not sure if there's a networking SE or if this might be more appropriate on SuperUser or something, but it feels right on SO. Drop me a comment ASAP if it's not appropriate here and I'll delete it and post to a suggested new location instead.
You might want to read about the C10K Problem. The article compares several I/O strategies. A certain number of threads that each handle several connections using nonblocking I/O is the best approach imho.
Regarding your specific project I think it is a bad idea to poll for a limited number of log items. When there is a peak in log activity you will miss potentially critical data, especially when you apply your optimizations.
It would be way better if the clients you are monitoring pushed their new log items to your server. That way you won't miss something important.
I am not familiar with the performance of ASP.NET so I can't answer if a single dedicated server is enough. Especially because I do not know what the specs of your server are. Using a reasonable strong server it should be possible. If it turns out to be not enough you should distribute your project across multiple servers.

{ ProcessName, NodeName } ! Message VS rpc:call/4 VS HTTP/1.1 across Erlang Nodes

I have a setup in which two nodes are going to be communicating a lot. On Node A, there are going to be thousands of processes, which are meant to access services on Node B. There is going to be a massive load of requests and responses across the two nodes. The two Nodes, will be running on two different servers, each on its own hardware server.
I have 3 Options: HTTP/1.1 , rpc:call/4 and Directly sending a message to a registered gen_server on Node B. Let me explain each option.
HTTP/1.1 Suppose that on Node A, i have an HTTP Client like Ibrowse, and on Node B, i have a web server like Yaws-1.95, the web server being able to handle unlimited connections, the operating system settings tweaked to allow yaws to handle all connections. And then make my processes on Node A to communicate using HTTP. In this case each method call, would mean a single HTTP request and a reply. I believe there is an overhead here, but we are evaluating options here. The erlang Built in mechanism called webtool, may be built for this kind of purpose.
rpc:call/4 I could simply make direct rpc calls from Node A to Node B. I am not very susre how the underlying rpc mechanism works , but i think that when two erlang nodes connect via net_adm:ping/1, the created connection is not closed but all rpc calls use this pipe to transmit requests and pass responses. Please correct me on this one.Sending a Message from Node A to Node B I could make my processes on Node A to just send message to a registered process, or a group of processes on Node B. This too seems a clean option.
Q1. Which of the above options would you recommend and why, for an application in which two erlang nodes are going to have enormous communications between them all the time. Imagine a messaging system, in which two erlang nodes are the routers :) ? Q2. Which of the above methods is cleaner, less problematic and is more fault tolerant (i mean here that, the method should NOT have single point of failure, that could lead to all processes on Node A blind) ? Q3. The mechanism of your choice: how would you make it even more fault tolerant, or redundant? Assumptions: The Nodes are always alive and will never go down, the network connection between the nodes will always be available and non-congested (dedicated to the two nodes only) , the operating system have allocated maximum resources to these two nodes. Thank you for your evaluations
HTTP is definitely out. Just the round-trip overhead of creating a new connection is a problem.
As for Erlang connections and using Pids, you have the advantage that you can subscribe to node-down messages and handle the case where a node goes down. A single TCP connection should be able to give you very fast speeds, however, be aware that it works like a long pipe: messages are muxed and demuxed on a pipe which can affect latency on the line. It also means that large messages will block small messages from getting through.
How much bandwidth are you aiming for, and at what latency? What is the 95th and 99th percentile of answering messages? It is better to put up some rough numbers and then try to target these than just having "as fast as possible". Set your success criteria first.
Q1: HTTP will add additional overhead and will give you nothing in my opinion. HTTP would be useful if you were designing a REST API. Directly sending messages and rpc:call look about the same as far as overhead is regarded.
Q2: Sending messages is much much clearer. It's the way erlang is designed. With RPC calls you must always track which call is executed where and under which circumstances which can be a huge issue if the two servers have state. Also RPC calls are synchronous.
Q3: I would use UBF if I can afford minor overhead, otherwise I would directly send messages between the erlang nodes. If the bandwidth is an issue other trickery would be needed as well. Like encoding the messages in same way and then using some compression algorithm to reduce the size of the message, alternatively I may ditch the erlang message passing altogether and use UDP sockets.
It is not obvious that ! is the best way to go. Definitely, it is the easiest and the code will be the most elegant.
In terms of scalability, take under consideration that to use rpc/! you have to maintain an erlang cluster. I found it painful having just 10-20 nodes even in private cloud. I would never recommend bigger deployments on e.g. EC2, where io/latency/network is not deterministic.
I recommend to structure the project in a way that will let you exchange communication engine in the future. Also HTTP is pretty heavy, but there are options:
socket-socket (tcp/udp/sctp)
amqp (many benefits connected to load balancing)
zeromq (even nicer than amqp)
Betting on !/rpc and OTP cluster is risky. You will fight with full mesh overhead, master election algos and quorum/partition detection.

Sending data between .net applications over the internet

I am sending small messages consisting of xml(about 1-2 KB each) across the internet from a windows application to a asp.net web service.
99% of the time this works fine but sometimes a message will take an inordinate amount of time to arive, 25 - 30 seconds instead of the usual 4 - 5 seconds. This delay also causes the message to arrive out of sequence.
Is there anyway i can solve this issue so that all the messages arrive quickly and in squence or is that not possible to gurantee when using a web service in this manner ?
If its not possible to resolve can i please get recomendations of a low latency messaging framework that can deliver messages in order over the internet.
Thanks.
Is there anyway i can solve this issue so that all the messages arrive quickly and in squence or is that not possible to gurantee when using a web service in this manner ?
Using just webservices this is not possible. You will always run into situations where occasionally something will take much longer that it "should". This is the nature of network programming and you have to work around it.
I would also recommend using XMPP for something like this. Have a look at xmpp.org for info on the standard and jabber-net for a set of client libraries for .Net.
Well this is a little off target, but have you looking into the XMPP (Jabber) protocol.
It's the messaging system that GTalk uses. Quite simple to use. Only downside to it, is that you will need a stateful service to receive and process the messages.
I also agree with #Mat's comment. It was the first solution that came to mind, then i remembered that I used XMPP in the pas to acomplish fast/ small and reliable messages between servers.
http://xmpp.org/about-xmpp/
if you search google you will easily find .net libraries which support this protocol.
and there are plenty of free jabber servers out there.
One way to ensure your messages are sent in sequence and are resolved as a batch together is to make one call to the webservice with all messages that are dependent on each other as a single batch.
Traditionally, when you make a call to a web service you do not expect that other calls to the web service will occur in a specific order. It sounds like you have an implicit sequence the data needs to arrive in the destination application, which makes me think you need to group your messages together and send them together to ensure that order.
No matter the speed of the messaging framework, you cannot guarantee to prevent a race condition that could send messages out of order, unless you send one message that has your data in the correct order.
If you are sending messages in a sequence across internet, you will never know how long will take the message to arrive from one point to another. One possible solution is to include in each message its position in the sequence, and in each endpoint implement the logic to order the messages prior to processing them. If you receive a message out of sequence, you can wait for the missing message, or request to the other endpoint to resend it.

Resources