⬆️ ⬇️

Jii: Scalable comets server and client

Continuing a series of articles about the Jii Framework . Today came the time of release of the comet, which I will discuss in this article.







Jii-comet is a scalable transport that is ready for high loads and bad Internet, realizing constant communication between the client and the server for instant data exchange.

')

Jii-comet provides a set of components and classes that make it easy to exchange messages between channels, subscribe to them, exchange data between servers, and so on. The module itself does not know how to deliver messages to the client and back, but it contains an abstraction so that any of the existing popular libraries (for example, socket.io , sockjs ) can do this, as well as reliably and scalable.



For those who hears about this framework for the first time, I recommend reading previous articles or visiting the site . In short,

Jii is a framework, whose architecture and API is based on the PHP framework Yii 2.0, taking the best sides out of it and retaining the benefits of JavaScript.


Overview



First, a little help on what comets are ( wiki ):

Comet (in web development) - any model of a web application, in which a permanent HTTP connection allows the web server to send (push) data to the browser without an additional request from the browser.


Jii-comet features



Customer:



Server:



Installation



A comet is installed as a component of the application , on the server and client respectively. On the server, the comets open and “listen” to data from the specified port, and the client, when the application is initialized, connects to this port and waits for information.



Consider an example of an application where a client subscribes to a test channel on a server and sends a message to it.

Server:



var Jii = require('jii'); require('jii-comet'); require('jii-workers') .application('comet', Jii.mergeConfigs( { application: { basePath: __dirname, components: { comet: { className: 'Jii.comet.server.Server', port: 4401, /** * * @param {Jii.comet.server.ConnectionEvent} event */ 'on addConnection': function(event) { Jii.app.comet.subscribe(event.connection.id, 'test'); } } } } }, custom.comet || {} )); 


Customer:



 require('jii/deps'); require('jii-comet/sockjs'); Jii.createWebApplication({ application: { basePath: location.href, components: { comet: { className: 'Jii.comet.client.Client', serverUrl: 'http://localhost:4401/comet', /** * * @param {Jii.base.Event} event */ 'on open': function(event) { Jii.app.comet.send('test', {message: 'Hello World'}); }, /** * * @param {Jii.comet.ChannelEvent} event */ 'on channel:test': function(event) { console.log('Income message: ' + event.params.message); } } } } }).start(); 


Next, let's look at server and client components.



Comet server





Jii-comet provides two classes for creating a server:



This separation is necessary for flexible application scaling. For example, you can create several processes with the Jii.comet.server.Server component, which will only maintain connection with clients, but not process business logic. And create multiple Jii.comet.server.HubServer processes that will perform heavy calculations. This will make the comet channel more responsive: if all operations were on the same server, complex operations would slow down the process, and all subsequent requests (even light ones) would be delayed.



If you do not have large loads or you do not know what to choose, choose the Jii.comet.server.Server component, as it contains all the functionality.



The configuration example for the server looks like this:



 application: { components: { comet: { className: 'Jii.comet.server.Server', host: '0.0.0.0', port: 3100 }, // ... } } 


A complete list of properties, methods and events is presented below.



Jii.comet.server.HubServer



Properties





Methods





Developments



For example, when you call Jii.app.comet.on ('channel: test', ...) , you subscribe to messages in the test channel. As above, an instance of the Jii.comet.ChannelEvent class with the parameters channel (string) and message (string) will be passed to the event handler as the first argument.

message - The event runs on any incoming message in the hub. The first argument of the handler will be an instance of the Jii.comet.server.MessageEvent class with the message (string) parameter.



Jii.comet.server.Server



Inherits the above properties, methods, and events, and adds the following:



Properties





Methods





Developments





Jii.comet.server.Connection



Contains client connection information



Properties





Comet client





The client is a little simpler: there is one Jii.comet.client.Client component that connects to one of the servers and communicates.



 application: { components: { comet: { className: 'Jii.comet.client.Client', serverUrl: 'http://localhost:4401/comet', autoOpen: true }, // ... } } 


A complete list of properties, methods and events is presented below.



Jii.comet.client.Client



Properties





Developments





Plugins



Plugins allow you to extend the capabilities of client comets. By default, the plugin is installed to automatically reconnect Jii.comet.client.plugin.AutoReconnect . The plugin is very easy to create and connect. The interface of the Jii.comet.client.plugin.PluginInterface plugin does not require the implementation of methods, but only provides access to the comet client via the comet parameter through which you can subscribe to comet events. The plugin is installed and configured through the configuration, by adding it to the plugins section:



 application: { components: { comet: { className: 'Jii.comet.client.Client', // ... plugins: { autoReconnect: { enable: false }, myPlugin: { className: 'app.components.MyCometPlugin' } } }, // ... } } 


How it works





At first glance, jii-comet is a wrapper over the library of comets-transport (sockjs, socket.io - to choose from), but this is not so. From the transport library, only the message delivery functionality to the client and back is taken. The implementation of channels, subscriptions, scaling and additional chips made it in jii-comet. Architecturally, "under the hood" jii-comet is divided into the following components:



Server:



Customer:



All of these abstractions can be configured and redefined via application configuration and context.



Examples





Example: The client sends a message to the channel.





jii-comet: The client sends a message to the channel




  1. The client sends a message to the test channel.
  2. The server process supporting the connection accepts this message and sends it to the hub ( Jii.comet.server.hub.HubInterface ).
  3. The hub sends this message to all server processes that are subscribed to this channel (or their connections are signed).
  4. Server processes receive a message and send it to connections that are subscribed to it.


Example: Client triggers server action





jii-comet: The client invokes the action on the server


  1. The client sends a request to perform the site / test action.
  2. The server process supporting the connection accepts it and drops it into the action queue ( Jii.comet.server.queue.QueueInterface ), as well as through the hub ( Jii.comet.server.hub.HubInterface ) sends a notification to all servers that process the actions ( listenActions = true ) that the queue is refreshed.
  3. One of the server processes with listenActions = true takes the request out of the queue (using the lpop method in the implementation of Redis) and starts the action itself.
  4. After performing the action, the server process sends the result of the action (response) back to the client. Since this server process does not have a direct connection with the client, it sends it to the hub ( Jii.comet.server.hub.HubInterface ).
  5. The hub sends a message to a server process subscribed to messages for this connection.
  6. The server process supporting this connection receives the message and sends it directly to the client.


In the third paragraph, a request from the queue could pull out any server process with listenActions = true . This works on the principle of "who had time" and, as a rule, the least loaded server will have time. Thus, balancing of action calls between servers and their processes is performed.



Internal communication channel



Jii-comet has an abstraction that allows you to use any library as an internal channel of communication between the client and the server. At the moment, an adapter has been made for the sockjs library, in the future it will also appear for socket.io .



In the configuration, the transport is declared in the transport section. By default, the class Jii.comet.server.transport.Sockjs in the north and Jii.comet.client.transport.Sockjs on the client are used.

Vehicles can be configured and redefined via configuration:



 comet: { className: 'Jii.comet.client.Client', transport: { className: 'Jii.comet.client.transport.Sockjs', transports: [ 'websocket', 'xhr-streaming', 'xdr-streaming', 'jsonp-polling' ] } } 


The end



Framework Site - jiiframework.ru

GitHub - github.com/jiisoft

Send your suggestions and suggestions to affka@affka.ru



Like the idea of ​​the framework? Put a star on the githaba !



Source: https://habr.com/ru/post/268817/



All Articles