
In September, a new feature appeared on 2gis.ru -
b2c-messenger for communication with organizations. The chat is very convenient when searching for a product or service: you can write to several companies at once, you do not need to listen to the voices of the answering machine robots or wait on the line until the operator clarifies the price or the balance of the desired product. Select a company, click on the message icon on the company card, and a chat will open.
To make an instant messenger, we had to sort out a little about how chat rooms work and what’s under the hood of “big brothers” like WhatsApp or Telegram. It turned out not so scary.
Why 2GIS Messenger
Perhaps, it’s worth starting not with the messenger, but with how we came to this idea. We used to show in the company email directory. Then added a form of communication with the company directly from the directory. They write less than they call, but the length of the chain of letters is on average from 2 to 10 messages. That is, an instant messenger is a logical development of an existing opportunity to send letters to companies.
')
How it works now

And even better - just try
to ask us a question . We are in Novosibirsk, and when in Moscow at 18:00, we already have 22:00.
A quick overview: choose a bike
First we looked at BaaS (Backend as a Service), such as quickblox.com, backendless.com, sendbird.com, etc. All of them provide tools for adding standard chat functionality to mobile or web applications.
The implementation of the main (sending email notifications in the company) and more advanced scenarios based on the existing BaaS solution will require us to both develop our own backends for integration through webbooks and super efforts for integration with the vendor's API. Therefore, BaaS did not suit us. In addition, we wanted to have full control over the features, that is, not to depend on third-party solutions. In the end, we are engineers and decided to experiment to get a new experience for us.
And how to deliver messages?
To make your backend for the messenger, you first need to deal with a bunch of questions: how to transfer messages from the client to the server and back, how to store them, how to handle a bunch of simultaneous connections, how to scale the service. Thought, google, collected ways to deliver messages in the table for comparison.
TableSorry, but we could not arrange the table in Habrareditor beautifully.The way | Description | Transport | Protocol | Browser support |
WebSockets | The client opens a persistent connection to the server using the WebSockets API. | Websockets API | TCP (requires HTTPhandshake to open a connection) | caniuse.com/#feat=websockets |
Streaming | The client opens a permanent connection to the server. | XMLHttpRequest (multipart onload), XMLHttpRequest (onprogress), Iframe tag | HTTP | caniuse.com/#feat=streaming |
Server Sent Events | The client opens a permanent connection to the server using the API Server Sent Events . | API Server Sent Events | HTTP | No support in IE, caniuse.com/#feat=eventsource |
Polling | The client periodically polls the server for new messages. | Any available | HTTP | |
Long polling | The client opens a long-lived connection to the server, which does not close until a new message appears or the timeout expires. Immediately after closing the connection, the client opens a new one. | XMLHttpRequest Script tag | HTTP | |
Browser Plugins (Java / Flash) | The client opens a permanent connection to the server using the browser plug-in API (Java or Flash). | Plugin API | TCP / UDP | |
Most modern chat applications use one of two methods: long polling or websockets. Websockets has several advantages over long polling (full duplex connection, no extra traffic during reconnections), it is widely supported in browsers and opensource libraries, therefore it seems to be the optimal choice for our task. There are also disadvantages: implementation differences in different browsers, more complex logic on the server.
The most common open general-purpose data transfer protocol is XMPP.
Positive sides | Negative sides |
IETF open standard | Redundancy of transmitted information |
A large number of opensource implementations | XML |
Opportunities for customization | Will require refinement to the specifics of our task |
Overview of large instant messengersMessenger | Delivery method | Protocol | Server | Storage system |
Whatsapp | Websockets | Started with XMPP, but then switched to in-house protocol | The entire server infrastructure is built on Erlang + FreeBS, it allows you to keep up to 2kk TCP connections on one server. We started on ejabberd, but it was very much modified by him afterwards. Yaws, lighttpd | Do not store message history on the server, messages are deleted from the server after being received by the client, mnesia |
Line | No web version, only Chrome app | Thrift for mobile customers | Java, C ++, Nginx | We started with a cluster of three Redis instances, after the explosive growth of the user base, “cold” data migrated to Hbase: message history and change history of users / groups / contacts, MySQL for backups and analytics |
Viber | No web version | In-house | C ++, hosted by AWS | We started with a samopisny in-memory repository written in C ++, then we switched to Mongo and Redis as a cache. Mongo did not arrange for performance, eventually migrated to Couchbase |
Facebook messenger | Long polling | In-house json-based for the web, Thrift for mobile applications | Erlang - message queues. C ++ - presence information service, message history storage. PHP - frontend, handles all user requests, except for long polling. Services communicate with each other through Thrift
| Queue on MySQL, HBase |
Slack | Websockets | In-house json-based | Java messaging server, LAMP for core app / APIs, hosted on AWS | Redis, MySql, Apache Solr |
However, having studied the solutions of various “big” messengers, we did not find any significant success stories of using XMPP without its subsequent refinement and customization. After thinking, we decided to develop a simple json-based protocol, which initially takes into account the specifics of our task.
Technology stack
Historically, our main backend service, IPI 2GIS, was written in PHP5. Two years ago we decided to leave PHP, migrate to Scala and Go. Go makes it very easy to build fairly complex concurrent programs. This was a decisive factor when choosing it as the main technology of the messenger implementation. And we already had some development experience on Go.
So, we write backend on Go, and frontend - on React + Redux. We chose RabbitMQ as the messaging system; for data storage we use Redis and PostgeSQL. We pack the application in a Docker container and deploy it via Gitlab-CI to the Deis platform.
As I said above, we wanted to use web sockets, but when it came to implementation, we slightly rethought the decision. The fact is that we wanted to release the feature as quickly as possible to test the hypothesis (the notorious MVP). To speed up, we decided to divide the logic into using web sockets to send data from the client to the server and the simplest REST API in the other direction.
What about notifications?
Suddenly, the most difficult to implement were notifications. It would seem that everything is simple: send a push to the phone, letters to the mail, display the notifications in the browser. But our task was to ensure that all notifications were read as soon as possible and at the same time did not turn into a stream of spam.
There is a solution called the cascade notification system. For example, we have three main channels: notifications on 2gis.ru, letters and pushes to the phone.
In this case, the notification system takes the form:
- check if the user is online → if yes, then we send him a notification in the browser;
- if the user is not online, we check if the phone is tied up → if yes, we try to send a push to a mobile phone, show a notification in the dialogs in the browser, do not send the letter;
- if that didn't work, then we send a letter;
- if the notification concerns the company - we observe the reaction for some time, and if there is no response after the notification in the browser and push, we still send the letter.
In fact, we don’t send push notifications from this scenario right now, but very soon we will learn how to do it.
Plans
In the near future we plan to add messenger functionality to 2GIS mobile applications, finish off the main functionality (the ability to attach an attachment to the message, browser pushes), implement advanced communication scripts (for example, request to several companies at once).
While companies are not used to the messenger, and not everyone responds quickly to messages. But we believe that interaction between people and companies through the text has a great future.