-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Terminologies
Pomelo has its own terminology, and here we will give a brief explanation of terminology, giving readers an intuitive concept, clarifying confusion while reading this tutorial.
Generally the gate server do not involve rpc call, that means it do not have port field in its configuration item, only has the clientPort field, and it is just use for frontend load balancing. Clients first often send requests to the gate server, and the gate server will assign client a specific connector server.The specific allocation strategies can be generated by developers, so that you can achieve the load balancing among various connector servers.
Connector server is responsible for receiving connection requests, creating connections with clients, maintaining clients' session information, receiving client requests and forwarding the requests to a specific backend server according to user-configured routing policy. When the backend server has processed the request or need to push messages to clients, connector servers will send messages to clients as an intermediate role. Connector server has clientPort and port, with clientPort is used for listening to client connections, and port is used to provide backend service.
Gate server and connector server are called frontend servers. Application server is backend server, which performs the application logic, providing services to clients. Of course, the clients' requests are routed through frontend servers. Backend servers will interact with each other through rpc calls. Since the backend server does not have a direct connection with clients, so the backend server only has the port field.
Master server is responsible for loading configuration files, starting the server cluster through the configuration file, and managing all other servers.
Pomelo uses RPC invocation for interprocess communication, the rpc call in pomelo can be divided into two categories by the namespace, the sys rpc call for the system, which is transparent to users, the system rpc call are:
- Backend servers push session information request to frontend servers
- Backend servers push messages to frontend servers through channel
- Frontend servers forward client requests to backend servers In addition to system rpc call, the rest are belong to user-defined rpc call, and this kind of rpc require users to complete the rpc server code.
Route is used to identify a specific service or the position where clients accept messages from servers. For server side, its form is generally . . , such as "chat.chatHandler.send", chat is the server type , chatHandler is a Handler defined in chat server, send is a method in Handler.For the client side, its general form is onXXX, when servers push messages, the client side would have the corresponding callback. Generally speaking the same type application server is not single, when a client request arrives, the frontend server will dispatch the client requests to a specific backend server, which requires a distributed routing function router. The router that can use user 's session as well as the contents of its request , do some calculations , it will map it to a specific application server id. The route can be invoked through the application of a type of server to configure their router. If you do not configure it, pomelo will use a default router which uses session routing function inside the uid fields, calculates fields crc32 checksums uid. Note that there is a trap that if the session is not bind with uid, at this time the uid field is undefined, and this may cause all requests are routed to the same server. So in the actual development developers still need to configure their own router.
In pomelo, the concept of these three kinds of session and two kinds of service: SessionService
and BackendSessionService
, is the most confusing place. And here we try to give some explanation, so you understand much more clearly.
Session is a abstraction of client connection , its fields are as follow:
{
id : <session id> // readonly
frontendId : <frontend server id> // readonly
uid : <bound uid> // readonly
settings : <key-value map> // read and write
__socket__ : <raw_socket>
__state__ : <session state>
// ...
}
- Id is the session id, which is unique in global and generated by the increment way;
- FrontendId is the frontend server id which maintains the session;
- Uid is the user id which is binded with the session;
- __socket__ is a reference to the native socket;
- __state__ is used to indicate the current state of session.
- Settings is a key-value map, which is used to keep some custom attributes of session.
From the above analysis, once a session is established, the field id, frontendId, __socket__,__state__, uid are identified, and they should be readonly. The settings should not be freely modified.
Therefore, in the frontend server, we introduce the FrondendSession, which can be seen as a puppet of real session in frontend server, FronendSession fields as follows:
{
id : <session id> // readonly
frontendId : <frontend server id> // readonly
uid : <bound uid> // readonly
settings : <key-value map> // read and write
}
The following is FrontendSession's function:
- Settings can be set by FrontendSession, and the values of settings in FrontendSession can be synchronized to the real session by invoking the push method of MockLocalSession;
- You can bind uid to the session by invoking the bind method of FrontendSession;
- Of course, the read-only fields in session can also be accessed via FrontendSession, but it can not send the changes to the original session.
BackendSession is similar to FrontendSession, it is used in backend servers and created and maintained by BackendSessionService.
channel can be seen as a container of players, it is used in the cases in which broadcasting is very frequent. When broadcasting to a channel, all the users in the channel will receive the broadcasting message. A player can be contained by multiple channels. Note that channel is server-local, that means application server A and B does not share their channel information.
There are four types of messages in pomelo:request, response, notify and push. Client initiates request to server, and then server returns a response after handling the request. Notify message is also sent to server by client, but it do not need a response. Pushing message is sent by server to client actively.
Filter can be divided into two categories:before filter and after filter. Before filter would do some pre-handling on the request such as recording log for user logining. After filter would do some post-handling on the request, it always do some cleaning up. In after filter, it should not modify the content of the response, because the response has been sent to client before entering into after filters.
Handler is used to do business logic, which is located between the before filter and after filter in the request-handling-chain, its signature is declared as follows:
handler.methodName = function(msg, session, next) {
// ...
}
Similar meanings before filter parameters . handler processing is complete, if necessary, the response back to the client , you can return the result packaged as js object passed to the back through the next process .
Error handler is is used to handle the exceptions generated from handling requests from clients. In error handler, it can record the exception log, respond error message to clients and so on. Error handler is optional, and it can be registered to pomelo framework using following if necessary:
app.set ('errorHandler', handleFunc);
The error handler's signature is declared as follows:
errorHandler = function(err, msg, resp, session, next) {
// ...
}
The pomelo framework is composed of a number of loosely coupled components and the pomelo framework can be regarded as a container of component. Each component defines callbacks: start, afterStart, stop.
In pomelo administration framework, there are three roles that servers will act: admin client, monitor, master.
-
Monitor will report its server status to master and respond to the instructions sent by master.
-
master, master server is responsible for collecting all the information of the server cluster and sending instructions to the server cluster.
-
client is a third-party administration client, it will connect and register to the master and then request the information about the server cluster or send instructions to the server cluster through the master.
Admin module is used for server administration. Each module defines four callbacks and all of them are optional :
- masterHandler(agnet, msg, cb) , it will be callbacked by master once receiving a request/notify from monitor;
- monitorHandler(agent, msg, cb), it will be callbacked by monitor once receiving a request/notify from master;
- clientHandler(agent, msg, cb), it will be callbacked by master once receiving a request/notify from a third-party client;
- start(cb), it will be callbacked to do some initialization after being loaded by the administration framework.
Plugin is a new extension mechanism and it is added since pomelo 0.6. A plugin is composed of several components and some event handlers to handle the event emitted by the framework. It provides a very flexible mechanism to extend pomelo.
we have briefly described some terms used in pomelo, and theses terms will be invoked in the folowing example. Next, we will go to our exampledistributed chat application, and we will get its source code and install it first.