-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Backend server
In this document, we continue to discuss about some content about user requests. The backend server is used to handle requests and do specific business logic. After receiving a request from a client, frontend server will analyze route of the request, check whether the request is valid, and then initiate an RPC(sys namespace) invocation to a selected backend server according to the configured routing policy. All request that the backend server receives are from RPC invocation initiated by frontend server.
While the backend server starts its handling-chain to handle its received request, if it only needs to respond to the client, then just return the response by RPC returning. However, in many cases, the specific request handling logic will push messages to other users. For example, in a chat application, when a user send a chat request, the contents of the chat requst must be pushed to other users in the same room. Of course, this user case is not only in backend server, front-end server may also have a similar case.
BackendSession component and Channel component(Channel component can also be used in frontend server) are used in backend server, they are used to push messages to specific users together. As we know , a backendSession can be treated as a proxy to original session that frontend server holds. BackendSession component is a component wrapper for BackendSessionService, it is used to create and manage backendSession for backend server, and by its method push/bind calling, it can set some customized properties on the original session that frontend server holds.
Channel component is a component wrapper for ChannelService, it is used to maintain channels, each Channel can be treated as a collection of user's id that has binded to certain session. It can push messages to users in same channel by calling Channel's methods. The following is a class diagram related to backend server:
-
All requests to backend server are received from the front-end server's RPC invocation, that means the requests that server component handled for the backend server are dispatched by MsgRemote, which is a RPC server-side service.
-
The RPC invocation from frontend server will carry the information used to create backendSession, in the backend server, BackendSession component creates and maintains session for this request. All the changing on backendSession will not affect the original session. But in some cases, it is inevitable to modify the original sessions. For example, in a chat application, a user's login request may need to bind a uid to original session, and set custom properties such as room id. These can be done by bind/push methods calling of BackendSession. In the backend server request handling-chain, all session arguments are BackendSessions, it does not directly reflect the direct modification on it to the original session in the frontend server .
-
Sometimes, users need to be grouped in order to push messages more conveniently. Also using a chat application as an example, members of a chat room should be gathered into one group, when someone speaks, it can push the message directly to this group. Channel is suitable to this case, each channel maintains a uid collection, calling channel's pushMessge method will push messages to all the users in this channel.
-
ChannelService also provides pushMessageByUids method, it makes message pushing not through a channel, but an user collection directly, which makes message pushing be more flexible. Meanwhile, ChannelService also provides a broadcast method, using broadcast method can broadcast messages to all the sessions that held in a particular type of frontend servers.
-
All the operations on BackendSession and Channel, whether it is a binding operation to the session id, or sending message through the Channel or through ChannelService broadcast method, in fact, are related to the communication with clients. Since backend server is unable to communicate directly with client, these operations are actually RPC invocations to frontend servers. Because the request that backend servers receive from MsgRemote carrays frontend server id and other information and BackendSession component will maintain it, therefore, at this time, when backend servers initiate RPC invocations to frontend servers for pushing message, it is no longer needed to calculate route because the corresponding frontend server id is known here.
The following is a sequence-like diagram about some typical scenarios:
-
The diagram above shows the control flow of the backend server. Firstly, it obtain request from MsgRemote, and then dispatch the request to server component, server component initiates handling-chain composed of filters and handler. In the handling to user request, the session argument in the filters and handler are BackendSession. When you call a method on these backendSession, such as bind, push, kick and other operations, BackendSession component will initiates an RPC(sys namespace) invocation to front-end server, and this RPC invocation service is provided by SessionRemote that is implemented in frontend server by default.
-
If handling-chain needs to push or broadcast messages to users, you can use Channel. The calling to pushMessage method of channel will push messages to a channel, and it can also use pushMessageByUids method of ChannelService. These operations are actually initiating RPC invocation to frontend server too, and this RPC invocation service is provided is ChannelRemote that is implemented in frontend server by default.
-
BackendSession is a proxy to the orignal session in the front-end server, when the back-end server needs to bind uid or set customized properties to the original session, it is needed to call bind and push, using unbind while unbinding an uid from session. If only calling set/get on BackendSession without push calling, then the modification of the properties of the BackendSession can only be avaiable in the latter part of handling-chain without any impact. For example, the builtin filter timeout, in the before filter of it , it start a timer and set the timer id to BackendSession as a property, this timer id can be access in the latter of handling-chain. So in after filter, it can obtain the timer id and clear it. This kind of modification to backendSession can be available only in the backend server without impact on the original session.
-
A session that maintained by frontend servers is corresponding a client connection. When a user logs in, it will bind the corresponding uid to its session. There is an option singleSession in sessionService , if set it to true, then it allows only one logged session for an user, when a new session is logging, the logged session will be kicked. Otherwise, it allows multiple sessions bind to same user, this is significant in practice, for example, the users' clients may be on various devices, multiple devices can be simultaneously online for a certain user.
-
Channel maintains a set of uid, each uid is corresponding to one or more session(s), an uid can join multiple channels. But channel in backend/frontend server is local, that means two backend servers A and B do not share their channel information when there is cross-server access to channel, it may produce channel not found error. When sharing channel among servers is required, it can be done using global-channel-plug-in provided by pomelo, which uses redis to maintain channel information, but stores chat information on the local server.
-
The request id is optional, if absent, that means the request is a notify that does not need a response from server.