The gRPC C++ API for creating channels returns a shared_ptr. The generated function NewStub returns a unique_ptr. However I've seen reports of people having issues trying to create multiple instances of a stub type, sharing a channel. Their solution was to share the stub.
It is not clear from the documentation or API if a client is meant to create multiple stub instances sharing the channel or share a single stub. Please clarify the conceptual relationship between stubs, channels, and unique client connections.
Diving a little deeper:
A server can serve more than one service and a client endpoint can use a single channel to connect corresponding stub types to each of those services. For that purpose, it is clear the different stub types share the single channel to talk to the server endpoint. Does gRPC expect only one client per channel for a given service or can I have multiple clients on the client endpoint talking to a single service? If allowed, how do I achieve multiple clients for a given service on a client endpoint? How does the server distinguish these as independent clients?
As an aside, This SO post indicates both Channels and Stubs are thread-safe. (The post is specifically for Java, but I'm assuming it carries over to C++).
I think first we need to clarify the definitions for channel and stub, according to the official documents :
channel :
A gRPC channel provides a connection to a gRPC server on a specified host and port...
Conclude : A channel represents a single TCP connection.
stub :
On the client side, the client has a local object known as stub (for some languages, the preferred term is client) that implements the same methods as the service.
Conclude : A stub represents a single client.
From reading many other materials, I'm sure that a single channel(tcp connection) can be multiplexed, and now we get two options to achieve it:
one channel <--> one stub
one stub <--> multiple streams
one channel <--> multiple stubs
one stub <--> multiple streams
the only difference is that whether to share a channel among the stubs or not. My answer is: Yes, you can, for the reasons:
your reports of people having issues example is written in ruby, but I can also find python examples standing on the opposite side. So the behavior may depends on language implementations.
the synchronous cpp client examples use one stub object to issue a rpc, and it doesn't have any stream objects associated with, then the only way for multiplexing purpose is just share one single channel object among the stubs.
Combining the above two reasons, I conclude that: sharing a channel among the stubs is valid in C++.
Now, back to you questions:
Does gRPC expect only one client per channel for a given service or can I have multiple clients on the client endpoint talking to a single service?
Sure, you can have multiple clients talking to a single service.
If allowed, how do I achieve multiple clients for a given service on a client endpoint?
You can just have multiple stubs generated either from one single channel or from multiple channels, former is a better choice for connection overhead considerations.
How does the server distinguish these as independent clients?
This is due to http2, it can be multiplexed and has its own rules to achieve this, what grpc need to do is just follow thoes rules.
Hope this helps!
Related
I have several Go and C++ services, that act as servers and clients, i.e. those are long-living services, that from time-to-time talk to other services.
I cannot find anywhere in gRPC docs whether the client channels and stubs should be long-lasting reusable objects or they should be created on every call. Or, maybe, I should create some kind of a channel/stub pool, where a pair of a channel and a stub exists, for example, for each thread and gets updated, refreshed on some interval or condition.
According to official docs, you are encouraged to reuse stubs and channels when possible.
https://grpc.io/docs/guides/performance/
Problem
We have a client-server application, server side is Glassfish 3.1.2. This app has many users, as well as many modules (e.g. View Transactions, View Banks etc). There are some long running processes invoked by client which run on server. Currently we have not found a nice solution to show the user what is going on on the server side. We want the users to get updated messages from server with given frequency. What would you suggest to use?
What we have done/tried
We (independently) used an approach with Singleton bean and a Map of client IDs similar to this, and it works of course. But then on the server side every method doSomething(Object... vars) must be converted to doSomething(Object... vars, String clientID) or whatever ID is type of. The client pulls data from server say once per second. I would like to avoid adding facades between server and client.
I was thinking about JAX-WS or JAX-RS, but I'm not familiar with these technologies deeply and not sure about what they can do.
Sockets
I should note that on the server side we have only Stateless beans (there is a reason for that), that is why I did not mention the use of Stateful bean (which is very good candidate I think).
Regards, Oleg
WebSocket could be a suitable choice, it allows the server to send unsolicited data to clients with no strong coupling, you just have to store a client id to map client connections to running tasks and be able to push updates to the right connection.
The client id/socket connection mapping can be maintained in a singleton bean using an in-memory structure, i.e. a hash map, or a permanent datastore for scalability purposes or in case you need a robust solution.
Some useful links to better understand WebSocket technology are this and this.
A quote from Java Web Services: Up And Running, Second Edition book :
"At present, the distinction between the two flavours of web service is
not sharp,
because a SOAP-based service delivered over HTTP can be seen as a special case
of a REST-style service;"
How ?
How?
I believe the writer's statement is incorrect.
What is SOAP?
According to wikipedia:
SOAP can form the foundation layer of a web services protocol stack,
providing a basic messaging framework upon which web services can be
built. This XML based protocol consists of three parts: an envelope,
which defines what is in the message and how to process it, a set of
encoding rules for expressing instances of application-defined
datatypes, and a convention for representing procedure calls and
responses. SOAP has three major characteristics: Extensibility
(security and WS-routing are among the extensions under development),
Neutrality (SOAP can be used over any transport protocol such as HTTP,
SMTP, TCP, or JMS) and Independence (SOAP allows for any programming
model).
As you can see, there really isn't anything in this description of SOAP that takes any ideological stance over what the structure of your API calls (url wise) must adhere to. Of course, soap uses XML, and XML can have a data structure that essentially works as the rule-set of your API call... thats cool.
In contrast, we have REST.
What is REST?
According to wikipedia:
The REST architectural style describes the following six constraints
applied to the architecture, while leaving the implementation of the
individual components free to design:
Client–server: Servers are not concerned with the user interface or user state, so that servers can be simpler and more scalable.
Stateless: The client–server communication is further constrained by no client context being stored on the server between requests.
Cacheable: Responses must, implicitly or explicitly, define themselves as cacheable, or not, to prevent clients reusing stale or inappropriate data in response to further requests.
Layered system: A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way. Intermediary servers may improve system scalability by enabling load-balancing and by providing shared caches.
Code on demand (optional): Servers can temporarily extend or customize the functionality of a client by the transfer of executable code.
Uniform interface: The uniform interface between clients and servers, discussed below, simplifies and decouples the architecture, which enables each part to evolve independently. (i.e. HTTP GET, POST, PUT, PATCH, DELETE)
Comparison
In my mind, it shouldn't be described as SOAP vs REST, it should be RPC vs REST. RPC is remote procedural call, which basically means that every single functionality of your API gets 1 distinct API endpoint, and so on. so, REST can do with 1 url what RPC does with 7. SOAP is RPC (right?)
Yes, both are web services.
But saying that an RPC API is RESTful-ish because its transmitted over HTTP is hardly grounds to say they are similar... from the detailed information above, you can see that REST takes a much more ideological approach to the structure, transfer, purpose, scalability, and state of your service, whereas SOAP doesn't really talk about those things, and presumably the developer can choose to do, or not do, those things.
In conclusion, more context is needed for me to really understand what point the author was trying to make. An RPC API can be similar to REST if you make it do RESTful things.. but that is really circumstantial, isn't it?
We have internal services in our application, which are basically developed as Thrift RPC services. Now, I need to expose these services to the client applications, which are outside of the core system.
Now, the question is:
should I expose these Thrift services directly to the client? Advantages of doing so would be least amount of work required. Disadvantage would be that the clients need to connect to these Thrift APIs as well as another interface, which already exists, so actually the client applications need to open more than one socket to make connection to the core system.
An alternate option would be to wrap these Thrift services in another layer, which will be ultimately delivered to the end clients. Disadvantage of doing this: doing marshalling/unmarshalling the data twice, once with Thrift and next time with another interface.
What should be the preferred way of handling this situation?
We would not expose these services directly to outside clients. We would build or use an application to configure a proxy that the external clients could connect to.
The advantages to this are:
No need to punch a hole in your firewall
Possibility to do an extra security check
Possibility to throttle access to the internal service
Less chance of a hacker being able to exploit service
this is my first question, so sorry if the form is wrong!
I'm trying to make thrift server (python) and client (c++).
However I need to exchange messages in both direction. Client should register (call server's function and wait), and server should listen on same port for N (N-> 100k) incoming connections (clients). After some conditions are satisfied, server needs to call functions on each client and collect results and interpret them.
I'm little confused, and first questions is "can this be done in Thrift"?
Second question is related to mechanism that will allow me bidirectional communication. I guess that I will need two services. One with client's functions other with server's.
But I'm confused with calling code. I understand one way communication (calling functions from server), but with calling functions from client side I have a problem.
Any suggestions???
Thanks!
Consider using boost::asio for your client side, though depending on your level of C++, the code may seem too dense.
If you're looking for a simple example, take a look at:
http://www.linuxhowtos.org/C_C++/socket.htm
It contains both server-side and client-side code. Both sides create a socket and two-way communication is achieved by each side posting data to the socket. The server side is generally multi-threaded (with one thread per connection). The client side can be implemented as a single-threaded loop that alternates between querying the socket for any incoming information, performing computations, and posting results back to the socket.
Since, you say you are having problem with calling functions from client side, here is a sample Thrift code with Java server and C++ client, where the client calls a function in server. http://fundoonick.blogspot.com/2010/06/sample-thrift-program-for-server-in.html
Hope this helps :)