Will each Graphql Subscription from same browser create one websocket connection? - graphql

I know what is graphql subscription.
My question is if each subscription will create one websocket connection?
Or all the subscription from each browser is combined to one websocket connection?
I couldn't find answer anywhere in document.

GraphQL itself purposefully does not specify a transport layer in the specification. Therfore the answer depends on the implementation that you are using but for the implementations it makes sense to have only one connection. In Apollo you can use apollo-link-ws to connect to the server. This link then creates (an keeps alive) a single socket to the server using subscriptions-transport-ws. It can also handle all GraphQL methods (not only subscriptions) using the web socket.

Related

Apollo-Server GraphQL Subscription on External WebSocket Server

So I have a bit of a question since I'm having a hard time wrapping my head around it. Currently I have a GraphQL API Server created using Apollo-Server and persisted using a local sqlite database. I have the queries and mutations working correctly.
I also have an external WebSocket server that constantly has messages (that match my GraphQL/Database schema) produced to it at say ws://localhost:8000/websocket. Is it possible to have my GraphQL Server subscribe to that websocket address and constantly parse those messages and use the appropriate mutation to insert into the backend database?
I would then have a Vue frontend that would constantly display the results (via Vue Apollo Clients WS subscription maybe?)
to have my GraphQL Server subscribe to that websocket address and constantly parse those messages
Typically no, its the other way around - you can make ws server to call graphql server to do the mutations. That is if you want to use WS as the primary transport layer for everything - queries, mutations & subscriptions.
But usually architecture separates queries & mutations because they are more stateless and critical from subscriptions which are more stateful (persisted connection)
client -> queries & mutations -> graphql server --> redis pubsub -+
|
client <--> subscriptions <-- graphql subscription server <-------+
(in simpler cases when you don't need high load, you can combine both servers to use in-memory pubsub)
BUT, if you very much want to, ofc you can write custom code to connect graphql server -> listen ws server in the background. See https://github.com/enisdenjo/graphql-ws#node-client for example
The problem can appear if you have some user context. You would need to either have custom connection where changes of all users happen. Or have a dedicated connection for every user
Yes , it can be done quite easily , just write a service worker or a worker thread that constantly checks for new messages
Can be done using worker_threads in node js
And if you need to implement it realtime
Make sure your worker thread starts a socket connection and is constantly connected to the port where you are publishing your messages
You can do it using socket.io library

With GraphQL is it possible to replace the websocket used for subscription with a message-based approach (e.g. MQ)

Whereas the corporate environment I am working in accepts the use of http(s) based request response patterns, which is OK for GraphQL Query and Mutation, they have issues with the use of websockets as needed for GraphQL Subscription and would prefer that the subscription is routed via IBM MQ.
Does anyone have any experience with this? I am thinking of using Apollo Server to serve up the GraphQL interface. Perhaps there is a front-end subscription solution that can be plugged in using IBM MQ? The back end data sources are Oracle databases.
Message queues are usually used to communicate between services while web sockets are how browsers can communicate with the server over a constant socket. This allows the server to send data to the client when a new event of a subscription arrived (classically browsers only supported "pull" and could only receive data when they asked for it). Browsers don't implement the MQ protocols you would need to directly subscribe to the MQ itself. I am not an expert on MQs but what is usually done is there is a subscription server that connects to the client via web socket. The subscription service then itself subscribes to the message queue and notifies relevant clients about their subscribed events. You can easily scale the subscription servers horizontally when you need additional resources.

How do I respond to multiple gRPC clients?

I am building an application which can have multiple gRPC servers and definitely will have multiple gRPC clients, I wanted to know, how to identify on server side that this is the client I am talking to and only send data to that client. I am using bidirectional streaming RPC and right now the data gets broadcasted to every client and I don't want that. What functions in go gRPC make it possible or how can I implement it?
There are two ways to read this question. One way is to read it as the auth problem as answered before. The second way is how I read it, as a connection/session problem.
When the client connects, the grpc server will invoke a function to implement the call in its own goroutine, and that function will be only talking to the client that initiated that call. So, the struct you registered as your grpc server will be shared among many connections, but each connection will run in its own goroutine, and will only talk to the client that initiated it. That also means you have to make sure the grpc server implementation is thread-safe.
You mentioned data is being broadcasted to every client? There is no broadcast in grpc, are you sure that's what's happening?
This sounds like a common authentication/authorization problem that ultimately won't have much to do with gRPC or Go.
You need a way for a client to indicate who they are. Personally I'm a fan of JWTs. In a standard HTTP request, there are authorization headers that can indicate who is making the request. Similarly, gRPC supports meta data attached to each remote call. In my current work project, every call must have a JWT in the meta data or else I don't process the request. Every call except the login endpoint that is.
I haven't looked into how to get details like a gRPC client's IP address or other information about a client's connection but chances are that anything provided by gRPC's generated code is something potentially faked by the client. When architected correctly, JWTs can offer cryptographic confidence that the client is who they claim to be.

What is the relationship between vert.x, sockJS, and websockets?

I'm extremely new to all of this, but from my understanding, websockets allow for a bidirectional transfer of information between browsers. Vert.x is a library that allows for asynchronous I/O. And sockJS is a JavaScript library that attempts to use websockets for communication, and provides fallback options otherwise.
But if I'm writing something in Java using vert.x, I don't quite understand how the pieces fit together. Does vert.x actually support websockets? Or do I need a combination of vert.x and sockJS to make that happen?
HTTP(s) is a stateless protocol, which means that once its job is done it will be idle till the next job is given.
So lets take an example of chat application, assume A is chatting with B using HTTP protocol. B has sent a message which is in server, now until A refreshes the browser, B's message will not appear. That's stateless behavior.
Coming to sockets, which is not stateless. Sockets use ws protocol which is always connected to the server. Taking the same example, now if B sends a message, A's socket will fetch and display to the browser, without the need to refresh. That's how sockets work.
To serve a webpage you need an http server. Similarly to use sockets, sockets server is needed. Which is provided by Vert.x. So Vert.x will start socket server, your browser will listen to that server using clientside sock.js file.

Which is better: multiple web socket endpoints or single web socket endpoint in Java EE7

Java EE 7 allows you to create new endpoints very easily through annotations. However, I was wondering is having multiple endpoints one to handle each message type a good idea or should I have just one endpoint facade for everything?
I am leaning towards having one single end-point facade based on the theory that each endpoint creates a new socket connection to the client. However, that theory could be incorrect and Web Socket may be implemented so that it will use just one TCP/IP socket connection regardless of how many web socket end points are connected so long as they connect to the same host:port.
I am asking specifically for Java EE 7, as there may be other web socket server implementations that may do things differently.
Just noticed an ambiguity on my question re: message types. When I say message types I meant different kinds of application messages not native message types such as "binary" or "text". As such I marked #PavelBucek answer as the accepted one.
However, I did try an experiment with Glassfish and having two end points. My suspicions were correct and that there is a TCP connection established per connected endpoint. This would cause more load on the server side if there is more than one websocket endpoint being used on a single page.
As such I concluded that there should be only one endpoint to handle the application messages provided that everything is a single native type.
This would mean that the application needs to do the dispatching rather than relying on some higher level API to do it for us.
The only valid answer here is the latter option - having multiple endpoints.
See WebSocket spec chaper 2.1.3:
The API limits the registration of MessageHandlers per Session to be one MessageHandler per native websocket message type. [WSC 2.1.3-1] In other words, the developer can only register at most one Mes- sageHandler for incoming text messages, one MessageHandler for incoming binary messages, and one MessageHandler for incoming pong messages. The websocket implementation must generate an error if this restriction is violated [WSC 2.1.3-2].
As for using or not using multiple TCP connections - AFAIK currently there will be new connection for every client and there is no easy way how you can force anything else. WebSocket multiplexing should solve it, but I don't think any WebSocket API implementation support it (I might be wrong..)

Resources