Azure Service Bus as Messaging System for "mass" client-server applications

Greetings to you habrovchane!
Before I tell you anything interesting, let me first introduce myself. We are a young company engaged in distance learning. In this blog, we will share with you our interesting findings, technical tricks and other things that we believe should be shared with the community.
Next will be a few words about us and, in fact, rendered in the title story about the non-obvious use of the
Azure Service Bus.
Who are you and what are you doing?
Some time ago, education concerned only computer science, and even then not everywhere. Since then, much has changed (in our country - to a lesser extent, in the States, for example - to a greater extent): many are already getting education online. Naturally, software solutions began to appear in the new field like mushrooms. And, as is usually the case, most of these samopisnyh systems provided very limited functionality. Such systems are still used in various educational institutions. Then large companies with serious decisions (for example, Adobe) began to pull themselves into this niche, but the verdict of the teachers who have to use it sounds disappointing. They are not comfortable using existing solutions.
Our company at this stage is developing the product of the same name (PENXY), which is a complex system for online training, both synchronous (similar to webinars) and asynchronous (similar to forums, textbooks, test items). The main feature of our approach is that we constantly discuss our solutions and ideas with teachers, trying to maximize the usability of the system for them. You must agree, really high-quality online education is great!
')
Therefore, if dear readers have any thoughts or wishes on how you think a truly convenient tool for distance learning should look like - we will be very happy to hear from you and will try to include these suggestions in our plans if possible.
Enough words, let's get down to business!
Our system is built on a client-server architecture using cloud technologies. Accordingly, in the course of design and development we faced various interesting problems and equally interesting (and sometimes rather extravagant) solutions. We would like to share a part of these observations with Habr.
Surprisingly, there are few articles on Windows Azure on Habré (well, except for general reviews and monthly mailings). The part of Azure called Service Bus is even less affected. In general terms about what it is, and why it is needed, you can read in the articles of David Cheppel. For example, on Habré, namely,
here and
here there is a translation of an overview article on Azure in 2 parts, which, in particular, describes the use of the Service Bus when building corporate systems. It may give the impression that this technology is needed only in order to bind together parts of a business solution located in the cloud and on-premise.
Despite the fact that the Microsoft “independent evangelist” Cheppel in his article considers only the indicated application of this technology, now this part of Azure has a fairly large and convenient Message Broker functionality. Since the writing of the article, there have been two changes: Microsoft has finished the functionality and changed the pricing policy. About the functionality a little later, and now briefly turn to the prices. In general, the pricing policy for the Service Bus, which was first conducted by Microsoft, severely limited the scope of the Service Bus: payment was made for each connection to the bus. In December, the pricing policy was changed, and now every transaction is paid for in the Service Bus. There is no payment for connections, but their number is limited. In fact, the Service Bus is now worth as much as Azure Storage. More details about the new pricing Service Bus can be found on the
official website.
As a result, the range of Service Bus applications has expanded significantly. But before proceeding to the description of the possible applications of this technology, I will talk about its device itself.
Hooray pictures!
Service Bus is positioned as a technology that allows you to organize the interaction between local applications and data located behind a firewall, applications in the cloud, rich desktop applications and applications on smart mobile devices around the world.
The main properties of the Service Bus:
- Securely opens access to external WCF-based web services, which are closed by firewalls and NAT routers, and without the need to open any incoming ports or even reconfigure the firewall or router.
- Provides secure inbound connections from devices outside the firewall.
- Provides a single namespace, which is completely detached from the geographical location. This means that such information is not contained in the name of the service.
- Provides mechanisms for publishing and searching for endpoints in the namespace.
- Provides the ability to forward messages. Supported one-way messaging, messaging on request / response model and p2p interaction.
- It provides the function of a message broker, in particular, enables asynchronous messaging (the sender and recipient of the message are not required to be online simultaneously). The infrastructure is designed in such a way that messages are securely stored until the recipient is ready to receive them.
- It creates and maintains endpoint services, and also allows tunneling between two endpoints, allowing bidirectional data transfer.
What was completely unclear to me when I began to understand the Service Bus is how convenient the Service Bus is in the role of a message broker, and the source of the messages can be both clients outside the cloud and roles in the cloud. Let's take an example for a chat and try to implement it on the cloud.
All clients are connected to our server in the cloud, one of the clients sends a message, some of the clients receive a message (that is, we assume the separation into rooms). But if everything was so simple! I’m not even talking about permanent bi-directional connections that need to be supported (so that customers don’t have to constantly ask the server if new messages have arrived, although of course this approach is also good). The thing is that for each role in the cloud created several instances. Given that we do not control what specific instance each client is connected to, there is a need to transfer messages between instances in one form or another. Moreover, given the fact that in one room there are significantly more people than instances, it automatically turns out that all instances have customers from this room. Those. it turns out that each instance transmits messages to all other instances. This is a completely natural approach; moreover, Microsoft
offers it in its own
labs . As a result, we get the following picture:
Each instance in the general case sends the incoming message to all other instances, they send it to their clients. Everything seemed great, but we will not stop at this. The fact is that such a scheme does not guarantee the delivery of messages. Indeed, Azure can kill a specific instance at any time, which means that we can lose the sent message. Therefore, we will have to complicate our scheme. We add there the message store and processing confirmation. It turns out something like this:
The alternative is to generally use Storage as a transit entity between instances, but this is not very important in this article. Generally speaking, it turned out to be a rather complicated scheme, which involves the use of Storage, several role instances and not the most obvious interaction. It turns out that in some cases our task can be solved much easier. We assume that there are less than 100 thousand rooms in the chat room, no more than 100 people in each room, and the rooms are statically or rarely changed. Such restrictions are not voiced by chance. Because I plan to use in this example Service Bus and one namespace, then the limitations are taken
respectively .
In the new scheme, each room in the chat is a
topic (a special entity that implements the public subscribe approach) inside the Service Bus. Each client connects directly to the Service Bus, sends messages to the topic and receives messages by subscription. It looks like this:
What about security?
It is important to understand that if you use simple Service Bus queues or one subscription to all clients, then each message in the chat will be delivered to the first registered customer, and that's it. That is why we use the functionality of topics, not queues, and create a subscription for each client. Unfortunately, this approach also has its disadvantages. The fact is that the Service Bus is not yet able to get a security token, which would allow, for example, only send and receive messages, but would not allow to create and delete topics. Those. if you allow the client to work with the Service Bus, then he gets full access with all the resulting security risks. However, this solution is also applied in practice, because with this approach you do not need any roles. In this case, the permissions in one form or another are either stored on the client in an encrypted form, for example, in keychains in poppies, or the server must issue them when the client connects, of course this implies a secure connection and a working webroll. In general, even if we decide that we need to ensure complete security and will use, for example, a webrol to proxy requests to the Service Bus (in order to hide this token from the client), the solution will still be easier, because many questions, for example , room management, are solved with this approach much easier directly with the capabilities of the Service Bus.
Separately, it is worth noting that the client does not have to be .Net-based in order to interact with the ServiceBus. Here, for example, a
link to this topic.
At this point I want to finish this short review. Thank you for your attention, I will be grateful for comments and suggestions for improvement.
At last
It is clear that to get this result, it is not at all necessary to take a ready-made solution built into Azure. There are many other ways to achieve the same (at first glance) results. The question as usual lies in the specifics of your tasks and needs. Of the possible applicants can be identified:
Low-lattency / High Throughput / in-RAM:
- NoSQL storage / caches with publish / subscribe functionality - for example redis (yes, the unix storage lives quite well in Azure, but with scaling problems so far)
- Implements Complex Event Processing patterns — for example, Microsoft StreamInsight , which can not only transfer data, but also perform detailed signal processing in real time. (and yes, it will soon appear in Azure too)
- ZeroMQ and other Messaging Queue Systems
Guaranted Delivery / Redundant:
- Msmq
- All possible implementations of the Enterprise Service Bus pattern (except for the Azure one considered), which work on the principle of “sent-forgot, will not be lost”
If the habr is interesting, we will be happy to tell you about the experience of working with such solutions and about the pitfalls with which we have already met.