📜 ⬆️ ⬇️

Do not postpone to the mailbox: 2GIS b2c-messenger



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.

Table
Sorry, but we could not arrange the table in Habrareditor beautifully.
The wayDescriptionTransportProtocolBrowser support
WebSocketsThe client opens a persistent connection to the server using the WebSockets API.Websockets APITCP (requires HTTPhandshake to open a connection)caniuse.com/#feat=websockets
StreamingThe client opens a permanent connection to the server.XMLHttpRequest (multipart onload), XMLHttpRequest (onprogress), Iframe tagHTTPcaniuse.com/#feat=streaming
Server Sent EventsThe client opens a permanent connection to the server using the API Server Sent Events .API Server Sent EventsHTTPNo support in IE, caniuse.com/#feat=eventsource
PollingThe client periodically polls the server for new messages.Any availableHTTP
Long pollingThe 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 APITCP / 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 sidesNegative sides
IETF open standardRedundancy of transmitted information
A large number of opensource implementationsXML
Opportunities for customizationWill require refinement to the specifics of our task
Overview of large instant messengers
MessengerDelivery methodProtocolServerStorage system
WhatsappWebsocketsStarted with XMPP, but then switched to in-house protocolThe 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, lighttpdDo not store message history on the server, messages are deleted from the server after being received by the client, mnesia
LineNo web version, only Chrome appThrift for mobile customersJava, C ++, NginxWe 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
ViberNo web versionIn-houseC ++, hosted by AWSWe 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 messengerLong pollingIn-house json-based for the web, Thrift for mobile applicationsErlang - 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
SlackWebsocketsIn-house json-basedJava messaging server, LAMP for core app / APIs, hosted on AWSRedis, 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.

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


All Articles