I'm trying to count any "new" client who connect to my HTTP server based on Netty 4 CR1.
Before CR1, it seems that channel.id was unique for any requests from a client.
Now, I have a different channel id per request.
I would like to understand what unique meant ?
In my use case, how can I detect if the request come from the same client.
The API say : Channel.id()
"Returns the unique integer ID of this channel."
Link: http://netty.io/4.0/api/io/netty/channel/Channel.html#id()
Thanks
It means what the javadocs says... It is unique per Channel which means per connection. So if multiple requests are served via the same Channel the id will stay the same as the connection is not dropped.
Related
Let's say I have a micro service which just registers a user into the database and we expose it to our client. I want to understand what's the better way of handling the following scenario,
What if the user sends multiple requests in parallel(say 10 requests within the 1 second) with same request body. Should I keep the requests in a queue and register for the very first user and deny all the other 9 requests, or should I classify each request and compare whichever having similar request body and if any of them has different request body shall be picked up one each and rest are rejected? or What's the best thing I can do to handle this scenario?
One more thing I would like to understand, is it recommended to have rate-limiting (say n requests per minute) on a global API level or micro-service level?
Thanks in advance!
The best way is to use an idempotent call. Instead of exposing an endpoint like this :
POST /users + payload
Expose an endpoint like this :
PUT /user/ID + payload
You let the caller generate the id, and you ask for an UUID. With UUID, no matter who generates it. This way, if caller invokes your endpoint multiple times, the first time you will create the user, the following times you will juste update the user with the same payload, which means you'll do nothing. At least you won't generate duplicates.
It's always a good practice to protect your services with rate-limiting. You have to set it at API level. If you define it at microservice level, you will authorize N times the rate if you have N instances, because you will ditribute the requests.
I have a complex problem and I can't figure out which one is the best solution to solve it.
this is the scenario:
I have N servers under a single load balancer and a Database.
All the servers connect to the database
All the servers run the same identical application
I want to implement a Cache in order to decrease the response time and reduce to the minimum the HTTP calls Server -> Database
I implemented it and works like a charm on a single server...but I need to find a mechanism to update all the other caches in the other servers when the data is not valid anymore.
example:
I have server A and server B, both have their own cache.
At the first request from the outside, for example, get user information, replies server A.
his cache is empty so he needs to get the information from the database.
the second request goes to B, also here server B cache is empty, so he needs to get information from the database.
the third request, again on server A, now the data is in the cache, it replies immediately without database request.
the fourth request, on server B, is a write request (for example change user name), server B can make the changes on the database and update his own cache, invalidating the old user.
but server A still has the old invalid user.
So I need a mechanism for server B to communicate to server A (or N other servers) to invalidate/update the data in the cache.
whats is the best way to do this, in scala play framework?
Also, consider that in the future servers can be in geo-redundancy, so in different geographical locations, in a different network, served by a different ISP.
would be great also to update all the other caches when one user is loaded (one server request from database update all the servers caches), this way all the servers are ready for future request.
Hope I have been clear.
Thanks
Since you're using Play, which under the hood, already uses Akka, I suggest using Akka Cluster Sharding. With this, the instances of your Play service would form a cluster (including failure detection, etc.) at startup, and organize between themselves which instance owns a particular user's information.
So proceeding through your requests, the first request to GET /userinfo/:uid hits server A. The request handler hashes uid (e.g. with murmur3: consistent hashing is important) and resolves it to, e.g., shard 27. Since the instances started, this is the first time we've had a request involving a user in shard 27, so shard 27 is created and let's say it gets owned by server A. We send a message (e.g. GetUserInfoFor(uid)) to a new UserInfoActor which loads the required data from the DB, stores it in its state, and replies. The Play API handler receives the reply and generates a response to the HTTP request.
For the second request, it's for the same uid, but hits server B. The handler resolves it to shard 27 and its cluster sharding knows that A owns that shard, so it sends a message to the UserInfoActor on A for that uid which has the data in memory. It replies with the info and the Play API handler generates a response to the HTTP request from the reply.
In this way, all subsequent requests (e.g. the third, the same GET hitting server A) for the user info will not touch the DB, no matter which server they hit.
For the fourth request, which let's say is POST /userinfo/:uid and hits server B, the request handler again hashes the uid to shard 27 but this time, we send, e.g., an UpdateUserInfoFor(uid, newInfo) message to that UserInfoActor on server A. The actor receives the message, updates the DB, updates its in-memory user info and replies (either something simple like Done or the new info). The request handler generates a response from that reply.
This works really well: I've personally seen systems using cluster sharding keep terabytes in memory and operate with consistent single-digit millisecond latency for streaming analytics with interactive queries. Servers crash, and the actors running on the servers get rebalanced to surviving instances.
It's important to note that anything matching your requirements is a distributed system and you're requiring strong consistency, i.e. you're requiring that it be unavailable under a network partition (if B is unable to communicate an update to A, it has no choice but to fail the request). Once you start talking about geo-redundancy and multiple ISPs, you're going to see partitions pretty regularly. The only way to get availability under a network partition is to relax the consistency demand and accept that sometimes the GET will not incorporate the latest PUT/POST/DELETE.
This is probably not something that you want to build yourself. But there are plenty of distributed caches out there that you can use, such as Ehcache or InfiniSpan. I suggest you look into one of those two.
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.
I am trying to figure out how to generate a ServiceProxy that points to the service that I'm currently executing within. I have a need to convey information about it, so that another service can call back into this specific instance: since it's stateful.
ServiceProxy seems to do resolution by partition keys. However, I don't see how I can obtain a partition key for the currently executing service. I can obtain the partition Guid. But, ServiceProxy cannot be used with that.
Example use case: I have a StatefulService which invokes an external HTTP API. It posts a message to this API, which results in the API calling back into my infrastructure after some period. The HTTP endpoint that I have built needs to resolve the original StatefulService in order to route the response back to it.
You can get the key range for the partition and send the low key value to the external HTTP API. When that external API needs to resolve the partition for the call back, it can use the low key value as the partition key, which guarantees it will fall in the right partition range:
Int64RangePartitionInformation partitionInfo = this.ServicePartition.PartitionInfo as Int64RangePartitionInformation;
long lowKey = partitionInfo.LowKey;
When a server accepts a client over a tcp/ip connection, a new socket is created.
Is it safe to use the LocalEndPoint port (from the client perspective) as an id?
Example (from the server perspective):
int clientId = ((IPEndPoint)client.RemoteEndPoint).Port;
On my local machine, the port seems to be unique, but with multiple clients on different machines, it may not always be the case.
My second question:
Let's say the port can't be used like a unique id, how the server (and hence the protocol stack) can differentiate between two client socket (from the server perspective).
TY.
The uniqueness of a socket is identified by 4 values: (local IP, local port,remote IP, remote port) and that's how the protocol stacks identify a connection.
Given this, you can have several connections from the same port number to same port number but e.g. to a different remote address. Typically you have to specifically request
permissions to use the same local port for more than 1 outbound connection.
Your example int clientId = ((IPEndPoint)client.RemoteEndPoint).Port; doesn't use the local port, but the port on the remote end. This is certainly not unique, as different clients might happen to chose the same port. Your server port is probably fixed, and will always be the same for all connections. Thus if you want something unique on the server side, you have to use the 4 values mentioned above.
However if you only need a unique identifier within your own client application among connections you've set up yourself, the local port will do.
Don't use the remote end point - create a GUID - for each (accepted)connection.
Pass the GUID back to the client socket - get the client to save it (much better than a HTTP session) and add the GUID to any subsequent HTTP headers directed at you :)
then!! the perfect need for a HastTable<> !!! only a couple of situations I know of!
Why not just use "client" as the unique identifier. A unique identifier need not be of a value type.
The short answer to the first question is probably no. The client OS will usually pick a port from a range. Even if that range is 40-50 thousand large, if your server is busy enough, sooner or later you may have the same port coming in from different clients. If it isn't a busy server you may get lucky.
Sockets are differentiated from each other based on pairs of address/port/protocol. The combined set of these values from the client and server will be unique.
Why can't you just use the client address and port as a temporary id?