Real-Time Applications

Fast and Scalable Front / Back-end Services using Ruby, Rails and XMPP

Fast and Scalable Front / Back-end Services using Ruby, Rails and XMPP

by Pradeep Elankumaran

In this presentation, Pradeep Elankumaran discusses the use of XMPP (Extensible Messaging and Presence Protocol) in building fast and scalable front and back-end services using Ruby on Rails during LA RubyConf 2009. He begins by explaining the fundamentals of XMPP, emphasizing its open standard, XML-based architecture, and its capabilities as messaging middleware. Key points covered in his talk include:

  • Introduction to XMPP: XMPP is often limited to traditional instant messaging in public perception, but it is a comprehensive protocol suited for various messaging applications.
  • Features of XMPP: Highlights include real-time presence updates, instant messaging, publish-subscribe mechanisms, and multi-user chat capabilities, making it a versatile tool for developers.
  • Challenges of XML: Although XMPP has advantages, it also faces challenges due to the verbosity of XML, which can hinder efficiency, especially regarding file transfers.
  • Use of Publish-Subscribe: This model is gaining traction for its ability to manage notifications efficiently across users and could be applied to microblogging and real-time collaboration functionalities.
  • Integration with Ruby on Rails: Pradeep discusses two Ruby libraries, xmpp4r and str-ruby, both of which facilitate XMPP integration but have challenges, particularly regarding documentation and scalability. He underscores the necessity of a good frontend approach to optimize performance.
  • BOSH Protocol: The presentation covers BOSH, which allows for long-lasting HTTP connections and enhances real-time updates in web applications.
  • Demonstration of Presently Application: The talk features a live demonstration of the Presently app, showcasing how it utilizes XMPP to achieve real-time message updates without overloading the server.
  • XMPP Server Recommendations: The speaker recommends ejabberd for scalability and robust performance while also mentioning alternatives like JabberD 2 and OpenFire.

In conclusion, Pradeep emphasizes the importance of selecting the right tools and protocols to create effective, responsive applications, and encourages further contributions and documentation improvements within the XMPP community, highlighting its potential as a powerful messaging solution.

00:00:12.200 Hey, my name is Pradeep. Can you guys hear me properly? I'm going to talk to you about XMPP and Ruby today, and that's my contact information.
00:00:17.720 I work for Inia, and we're based out of Washington, DC. We specialize in design, development, and strategy for applications. Our flagship product is Presently, and we also do consulting.
00:00:30.439 We're also based out of Atlanta, and our employees are actually scattered across various locations.
00:00:43.800 So, what is XMPP? How many of you have actually heard of it? Can someone who knows about it explain the context they know it in?
00:00:56.280 For a lot of people, the only context they know is traditional instant messaging, and I'm trying to change that. XMPP actually stands for the Extensible Messaging and Presence Protocol. It falls under a class of software known as messaging middleware. Today, I will talk about middleware as well.
00:01:24.240 XMPP is completely XML-based. There are various XMPP servers; one of them is called OpenFire. I’ll talk about this a bit more later. XMPP is most known for being the backend for many messaging systems, and you can read more about it at xmpp.org, where you can find all the listed features.
00:01:49.119 The good thing about XMPP, and there are quite a few, is first and foremost that it’s open. Anyone can contribute features and comment on those already submitted, and you can write your own XMPP service. Everything is open and also standardized by the Internet Engineering Task Force (IETF). It’s decentralized; you can run your own servers anywhere, and most of these servers can actually communicate with each other. XMPP is very mature, having been around for about 10 years, and it's catching on more now as more people start contributing. It's highly customizable, especially if you choose the right XMPP server. Since it's message-based, XMPP is also pretty fast, as most of the servers are optimized for sending messages to various clients quickly.
00:02:26.440 However, the bad news is that XML is very verbose, and some people call it over-engineered, but I don't see it that way. The documentation is readable, but it’s not outlined properly. Most of the people who wrote the documentation focused more on the specifications than on teaching how to use it. Luckily, there are efforts underway to improve this, and you can find many blog articles and other resources. One challenge with larger networks is that presence is very important, leading to a lot of data overhead just for sending presence data, to check if someone is online.
00:03:11.799 Another issue is that you can't send unmodified binary data file transfers because everything must be in XML—which is not very optimal. A simple XMPP stanza looks like this: you can have a message from one person to another, with a body that is as basic as it gets. The JID (Jabber ID) consists of the username and the server name, which serves as a unique identifier for every user, followed by a resource identifier which represents a client connected to the server at that time. You can connect using multiple clients on multiple machines, and you can set groups and priorities to ensure certain clients receive messages faster than others.
00:03:41.959 Some features of XMPP can be found on xmpp.org. The first important one is presence—indicating whether someone is online or not. This helps remove a lot of overhead when passing data around. Then there's instant messaging, which I will elaborate on later. The publish-subscribe model is quite interesting; when you post something to a node, everyone who subscribes to that node receives it immediately. I'll talk a bit more about this soon. Multi-user chat allows you to participate in conference rooms and connect to various XMPP servers while talking to people on other XMPP servers. Personal status updates work, for example, when you're using an app like a music player, and it instantly updates what you're playing across the network for all your friends to see.
00:05:08.160 Now, moving on to the future and what is happening right now—are there any questions so far? I want to discuss the publish-subscribe method first. It’s gaining traction as we realize certain architectures aren't set up to handle, for example, what Twitter or similar services require. Presently is quite similar to Twitter in some aspects, so we had to explore this, and we discovered that publish-subscribe is indeed a viable option for us.
00:06:13.240 Essentially, when there's a node on an XMPP server, people can subscribe to that node, and the moment someone publishes something, everyone will get a notification. The stanza for this looks like an IQ stanza set to publish data. In this case, we're publishing to Apple services, and when the message is published, all subscribers will receive an update in real-time.
00:06:54.320 Using publish-subscribe, we can accomplish a lot of exciting things. For instance, we are using a microblogging service. How this works is everyone who is registered has an account on our XMPP server, and, like changing songs, you can update your status. Whenever you change your status, everyone who follows you instantly gets an update. We can also do real-time searches; for example, if Google acquires Twitter, they could create an updates feed and subscribe to receive immediate notifications of new updates. This could facilitate real-time topic tracking, akin to RSS, though setting up those feeds would require considerable work behind the scenes.
00:08:21.680 Furthermore, collaborative editing could theoretically be done using publish-subscribe. Imagine a single text box where multiple users are making changes that get pushed to the server and distributed to all users in real-time. Any questions about that? Okay, moving on to real-time user interfaces. How many of you have used Presently besides me and Brandon? Presently has recently been updated to be much more dynamic. Previously, it relied on jQuery, but now it uses XMPP to display messages in real-time, akin to a Twitter-like interface but much more lively.
00:09:16.040 We achieve this using a method called BOSH, which I'll explain in detail shortly. What I want you to take away is that JavaScript-based XMPP clients are very mature right now, and you should leverage them to enhance your user experience. We use jQuery in conjunction with this, achieving close to 100% real-time updates if you set it up properly.
00:10:04.960 I want to demonstrate how to work with Ruby and XMPP on the backend, providing you with the libraries you'll need so that you're on your own from there. On the frontend, I will show you how to connect to your web server and client using JavaScript. Presently utilizes a BOSH user interface, providing 100% real-time updates. Does anyone here work with Drop.io? They have developed a new interface that is quite impressive.
00:10:34.799 Now let’s talk about the backend. In my opinion, there are only two good Ruby libraries available for XMPP. The first one is xmpp4r, which has been around for a number of years. It’s full-featured and event-based, but the documentation is nearly non-existent. It took me quite some time to figure out how things work, and because of the threading model, you can’t run it directly in a Rails application. You’ll have to run it externally and connect it with Rails, which can be complicated.
00:11:19.200 I would recommend xmpp4r for XMPP applications that don’t require Rails directly, such as certain Twitter-like tracking applications. For example, TwitterSpy is an open-source Ruby project where you can connect to various accounts and track specific topics. However, I believe it hasn't been optimized for scalability, so I wouldn’t recommend signing up if you're afraid of it slowing down. At the moment, we are looking for contributors for str-ruby, which is built off a solid XMPP library.
00:12:51.919 Str-ruby is mostly ready, but we are not ready to release it publicly as we don't want to end up providing extensive support due to the lack of documentation. If you are a good documenter or can condense complex code into a user-friendly interface, we would love your help. I plan to work on this and put up some documentation after the conference and will share my Twitter handle for updates.
00:13:58.240 The good news about Str-ruby is that you can run it within a Rails application, avoiding the need to run it separately. However, you will have to connect to the server every time, which introduces some overhead, but it won't significantly affect response times. When working on the backend with XMPP, I recommend not performing long-running tasks in the Rails application and always checking your timeout settings.
00:14:45.360 If you're using Ruby and XMPP, I strongly suggest doing most of your work on the frontend. It's advisable to use a JavaScript-based XMPP client in the browser, allowing it to receive XMPP messages directly. This will help keep your Rails app responsive and fast. We can leverage a protocol called BOSH, which stands for Bidirectional Streams over Synchronous HTTP. Because HTTP is typically a request-response protocol, it doesn’t naturally support long-running connections.
00:15:34.320 An alternative for enabling long-lasting connections is Comet. Comet uses a single persistent connection to the HTTP server. It survives disconnections and can maintain a continuous after-stream through long polling requests. If you've ever watched live coverage of an event on a website where updates seemed to arrive in real-time, that was likely a Comet-based push service. BOSH, however, can manage connections more robustly by handling disconnect switches and shifting between networks seamlessly.
00:16:51.960 In brief, the client connects to a BOSH Connection Manager, which forwards the requests to the XMPP server. Most contemporary XMPP servers, like ejabberd, have an embedded BOSH connection manager, eliminating the need to run it separately. The BOSH protocol creates a continuous back-and-forth chain between the client and the connection manager, allowing for messages and commands to flow seamlessly.
00:17:35.879 With BOSH and JavaScript, we can craft responsive user interfaces, connecting seamlessly to the XMPP server through a robust protocol developed by Jabber Mofet, known as SCo. This technology powers Presently, and I highly recommend it if you’re looking to create excellent user interfaces.
00:18:14.640 Now, I want to demonstrate the Presently application. As you can see, this is our internal interface. I assure you that it’s safely displayed without showing any sensitive details. At this point, it’s connected to the XMPP server, and I’ll provide a demonstration running through the app.
00:18:56.640 If I send a message through this interface, it will be posted to Rails, which will forward the update to the XMPP server. The message will then be sent back to the browser using BOSH. Notably, during this process, we are not making any requests from the Rails server; it simply posts updates, and the XMPP server is responsible for forwarding the messages.
00:20:12.000 This architecture allows our client to remain responsive. Previously, we used a basic, regularly polling setup that led to poor responsiveness when the load increased. To scale effectively once users started coming to our site, we transitioned to our current setup where the client posts to Rails for updates. Rails then passes the updates on to ejabberd via str-ruby, maintaining robust communication between the client and the server through BOSH.
00:21:24.180 This system has proven effective; our load averages are exceedingly stable, allowing us to run the entire application on a single machine without performance issues. We utilize ejabberd, which is written in Erlang and can scale effectively. It's actively maintained, and we have customized it for our needs, but I wouldn't necessarily recommend that level of customization unless you're experienced with XMPP.
00:22:55.360 Others, like JabberD 2 and OpenFire, are good alternatives that are actively maintained and customizable. They both have large communities with plenty of plugins. For basic XMPP functionality involving message exchanges, they are great options. Procity, a newer option, is written in Lua and claims to be lightweight and extensible, so if you're interested, you should check it out.
00:24:05.720 Ultimately, I want to convey that many enterprise solutions are already available for common problems, and a lot of them are well-documented. As time goes on, the field will only improve with contributions from those who want to help enhance these systems.
00:25:17.240 Now, are there any questions? What kind of throughput do you get on the JavaScript XMPP4? Well, most of your messages will go through JavaScript, so if users are utilizing the browser as a client, messages will pass directly through the JavaScript interface.
00:26:03.720 As of now, we have over a million updates, and most of these went smoothly through the server without a hitch. But on the client side, we ensure that our implementation is robust, so even if multiple updates come through at once, they should arrive at the browser without crashing it.
00:27:16.320 Regarding whether we're still using a separate BOSH connection to communicate with other Java servers, we're currently working on that. ejabberd has powerful gateway support, and we're aligning our Ruby implementation with it, which will improve connectivity for Ruby developers.
00:28:38.399 Lastly, do you know anything about the XMPP implementation in Verbra? They utilize XMPP for presence updates, but I haven’t looked into it in depth. It seems their system works well with working with updates, but I would need to confirm more specific details.
00:29:55.640 To manage updates effectively, we ensure that when someone signs in, they catch the latest from the database. Thus, only new updates are sent to connected clients directly to avoid loading unnecessary data.
00:30:43.920 Thank you all for your time!