 My name is Vishnu, I work at DirectEye on a product called Toptor2 and you can find me here. Now, I need to talk about the product before I talk about why we built NodeXMV Bosch. So it's a hosted chat solution for teams and workspaces and we're going to be supporting other networks. So essentially it's a chat client and server and we want to provide services over all of these and our eventual goal is provide an unbeatable experience for chat followed by world domination. So the point is that we want to build this client on web technologies. So we want to be a client for all platforms and that includes the web, so which means that you want to run on most modern browsers and that could be a bit of a problem when you're working with chat because traditionally with chat people use XMPP which is an open standard communications protocol and it's a streaming protocol. So most clients that you'll see XMPP clients, what they do is they establish a socket connection and then this bidirectional transfer of data. The server is sending data back. Now it's a chatty protocol, it's not so easy with if you want to make sure it works on all browsers. Now, WebSockets is also an option but I mean WebSockets is still in draft, the draft is changing. We ran into the same problem that you did that suddenly version 00 went to version 10 on Chrome. So yeah, I mean WebSockets is good probably in the future but for now you can't rely on all browsers having it. People are using older browsers so you can't necessarily rely on WebSockets being an option. So then the other option is HTTP polling. A couple of problems with this, one is there's always a trade-off of responsiveness versus faithfulness. You can keep polling waiting for data but then if you slow down then you might never get a message there from the server. So both of these are problems. Secondly ordering is not guaranteed, you know the server sends you a message, you don't want the messages in the opposite order. I mean it's, it could be okay for maybe a multi-user chat sometimes but there are other things you know sometimes you want to know if a person went offline and online. You play it in the wrong order and your friend is online but you think he's offline. There are all these issues why you want to make sure that your packets coming in the right order and you know you want to sort of be the optimum point over here and Bosch is sort of the solution for that. It's a biorection streams over synchronous HTTP, there's a spec you'll be able to read. And this should work on all browsers. Essentially what you do with Bosch is you know you send multiple, your server holds multiple requests, multiple connections and the client is expected to establish a new connection anytime it gets a response. So I mean the spec is quite detailed if you look through it you'll find that it even handles the problem of ordering because packets typically have an ID and you have to make sure that you acknowledge every packet and so on. So I mean as part of our problem because we wanted to provide chat we thought we'll build a Bosch server. So the next question was the choice of technology or why we chose Node.js. So thing is that we had a lot of expertise in Java but it kind of felt like this problem is a really good fit for event driven architecture with NIO. I mean really what you're doing is converting, you're taking data over HTTP for the HTTP transport and you're just picking one protocol to another protocol. So there isn't much in terms of computation you have to do. This link is really good to talk about the C-10k problem which is what happened when you want to have a lot of connections, you know a lot of clients connected to a single server. How do you make sure you don't consume too much CPU or memory and so on. Actually memory more than anything else. And many NIO systems essentially sort of solve this problem and in fact the first draft of what we wrote was on Python Twisted which is also an event driven system. So why Node.js? So it boils down to three things for us. There's the V8 engine which is really, really fast, right? Almost every API is non-blocking. Now this is more important than it might seem at first sight. A couple of things. One, any library you use for Node you can use safely. I work with Event Machine which is the Ruby equivalent. And the problem you have over there is while there are a lot of plugins, for every single plugin you have to look through all its dependencies and make sure that somebody out there isn't making blocking calls that might suddenly stall your server. So with Node you almost never have that problem. There are very few blocking calls you can make. And the second advantage of the API being non-blocking is a lot of work has been done to make sure that event driven code looks elegant. So you want to program in a non-blocking manner. So both of these mean that if you're solving a problem and you want to use NIO, it's more fun to do it on Node and it's safer to do it on Node. That's the reason we pick Node. The third reason of course is that we have a fair amount of JavaScript expertise. You might as well leverage it instead of picking some new technology. So that's it. Now there were a couple of concerns of course that we had to deal with. One is Node.js immature or not. Is it possible that we will not be able to find what we were looking for? Would we have to build everything from scratch? Was it unproven, that sort of things. But anyway, we went ahead and built Node.xmpbbosh. This was an open source project by Dhruv Matani who is a former colleague of mine. And it's hosted here. So you can always download it and contribute. It now supports WebSockets too. So if that's what you want to do. So what can you use it for? Well like us, you could build a web-based chat client. But really anything which uses bidirectional streams. So gaming, trading applications and so on. The other thing you can use it to do is get past firewalls. Because a lot of firewalls might block other ports. You might have a server that's already written. And you want to listen on port 80 and then forward it to this other port of yours. So I mean here are the reasons why you might want to use this project. Now the primary components is just these four things. There's the Bosch bit which sort of actually handles all the Bosch protocol piece. Make sure that it handles the ordering and the resending packets in case they missed and so on. There's a lookup which I mean is really, really small. And then there's these two pieces which actually handle the XMPP for us. The idea being that if you want to do something else, you just replace this, swap these out with something else. So that's the whole thing. And the way in which we sort of do this decoupling and communicate across them is the event emitters of Node.js. So one thing we discovered while working with Node is that there are plenty of libraries. It looked like that would be a problem in the beginning that you might have to sort of... What's the word for this? Something in the wheel. Renewing the wheel. Thank you. But yeah, it turned out there's a lot of things that we wanted that came up. I mean, there are libraries to do function programming in JavaScript. I think somebody is... I mean, they're a talk on underscore.js and so on. So yeah, pretty much everything you wanted you could find easily. That was the point. One thing we also decided to do was sort of externalize components, give back to the community. So for example, we pulled out this thing called the event pipe, which really was nothing to do with Node.js to be washed by itself, but it was something we were using. Might as well make it available and so on. So I was talking about event emitters earlier. The event emitters are really nice. I mean, if you talk to anybody about Node.js, I think this is one of the things that will come up very early. The API is really beautiful. It's got a really simple API for events. It's built into the language. It's sort of part of Node.js almost. And you'll find libraries built over this. If you want to use event emitters, you add event emitters to your prototype chain and that's it. You initialize the construction and you're done. It looks like this. Open it.on whatever and that's it. And similarly, you can just emit an event any time you want. So the API is that simple. It's very nice. I mean, typically you'll find that any app built with Node, this is pretty much how they're decoupling their system. It's just events from one place to another. Oops. So this is what we were using for quite a while. At some point down the line, we decided that we had another problem that we wanted to solve. So we've got a plugin architecture that allows us to introduce other plugins, which I'll talk about later. Sometimes what we wanted to do was an event was being fired, but some plugin might choose to suppress the event and so on. Similarly, we might want to emit our own events. I mean, you can emit your own events, of course, but if you wanted to suppress events and make sure they don't go on and you want to make sure it's easy for somebody who's following the code to understand that this event could be suppressed by this client and so on. The event pipe was introduced. The idea is, it's got an API very similar to the event emitter. It takes an ordered set of listeners. The idea being that when you sign up, you give it a priority and say, you know, I'm expecting to be so and so and so. And then you can build another abstraction over it to make sure that, you know, it's in one place, the order is visible to somebody. But the point is that, you know, you know for a fact that your listener is X position over it. So now you can cancel the event and so on. You can get that here. Okay. The next thing I wanted to talk about is the WebRipple. This is awesome. The WebRipple is a, I mean, you know what a repel is in Node, right? You can load up the repel and you can just type code directly in there and so on. And the WebRipple is a project just like that. It listens on a particular port. It's a, I mean, HTTP, this thing. You go in there, you can start typing JavaScript code and execute it, arbitrary Node code. But the nice thing is, it's great for monitoring. So let me show you what it looks like. So, you know, if I hit that API, I get this. And you can go deeper. You know, I can look for something specific. So for example, if you're using some sort of tool which is going to graph something out for you or monitor something for a dangerous limit or whatever, you know, you can just keep, you can just provide HTTP endpoints that you keep hitting. And the way you do this, let me see if I have the code over here. Yeah. I'm running on localhost. So, no, but, yeah. And of course, it's secure in some way or the other, which I'm not going to talk about. Well, basically, okay, I'm not able to pull this up here. Basically, you start up the web repel and then there's a context on which you can just attack stuff. So whatever objects you want to expose, you add to it, and then suddenly they're available over here at that path. And then it's just A dot B dot C or whatever. So that's if you want to get and attach it to a tool. The other option, of course, is that you can actually, yeah. So we start up the web repel with the application and we expose whatever we want on it. And over there, somebody could go in and type arbitrary code. You could do other things with the web repel, though. Every time I run it, it's execute. The other nice thing about it is that you can change things at runtime. You could set the log level to debug and, you know, while it's running, which is great. I think I can actually do that right now. Well, I mean, once you have the end points up to you to figure out how to secure it, that's a different problem. So I think, oh, damn, I don't know what I've done. Never mind. I can't fix this now. I just wanted to show you that, you know, at runtime, you could actually switch the log level to debug and start debugging it and so on on production. So that's useful. Similarly, there's the plug-in architecture of ours, which I'll talk about in a bit, where you have plug-in that do things. So you can test your plug-in at staging or whatever. Without taking your system down, you can hot deploy this, load it up, unload it whenever you want, and so on. So this is really great, the web repel. Again, something that, you know, you should consider using. Oh, yeah, this is the hot deploy plug-in. So you can just load the plug-in via the web repel and just make sure that, you know, whenever you unload, everybody's sort of taken care of making sure that unloading is safe and so on. The plug-in is internal, and it's not an internal to, no, it can be washed. It's something else that we've written, but it's really small. So we didn't bother putting it into the Bosch server. The Bosch server by itself is separate. Yeah, pretty much. I mean, we just find the location of this thing. We require it and run it. So, you know, you just have to say load and name. It will require a file of that name. And on unload, we expect to call something so you can do whatever cleanup you want. Cool, then. Okay, so we did some performance tests. This, an intern who was working with us, he wrote this little stress tool, which you can get there. And running on an Intel sort of dual core machine, 2.4 gigahertz. Of course, Node, of course, runs on a single core. We were able to process about 1,650 requests per second. Now, we kept increasing the number of clients. So, I mean, for 100 clients or 1,000 clients, it was the same. This was sort of the limit that we were hitting. And we found that our limit was essentially CPU. It was in memory. It was in anything else. It was in IO. It was CPU. So that's probably the best position to be. The thing we were wasting the most, I mean, we were spending the most time on is XML parsing. So if you want to speed up anything, that's the thing we have to look at. We haven't really stressed to see how many clients we can support. But I mean, we expect that if anything else should increase memory, not CPU. So that is the second bottleneck that we'll have to hit at some point. But at the moment, this is what we were looking at. So that's pretty good. Yeah, it would. I mean, we were testing it with really simple messages. It would because you're sort of doing an XML parse. I mean, that's where we spend most of our time. So it's that bit that we had to worry about. Yeah. This was tested sending messages back and forth to between two people and so on. And as far as scaling, I think the important thing to make sure over here is that specific clients go to the same instance. So we use Nginx. And so we set a cookie which you can use to determine which server you're hitting and so on. But yeah, you can just run as many instances as you want. As long as you take care of this, you're OK. This is necessary for the ordering of packets and so on. Well, we're not currently using WebSocket in production anyway. So yeah, that's what we're using for scaling. And we're just using cookies. I think I went really fast because I'm on the question slide already. OK. So the question is how is ordering maintained with an event-read model? So I mean, are you talking about the ordering of packets or how do you make sure that you process events in the right order? Yeah. Yeah. But as we process each message, all we're doing is sending it down to the XMPP server. Yeah. So I mean, very likely to lose sequence is the bit where we're making HTTP calls, right? Because the separate calls are sending separate packets. But every message on Bosch has a request ID. So we make sure that, you know, if I process a packet number 10, I have already packaged a process packet number 9. That's part of the Bosch spec. It's in production right now. I won't be able to give you the number of off-hand of how many requests you're processing. I can't access the WebApple from here, clearly. But, sorry, again, I don't have the number of off-hand, sorry. We just tested the tool. But in terms of our actual listing right now, we're well below it. So we haven't really looked at that yet. We tested this on a, I mean, I saw, not even a representative machine of production, something really, so yeah. I mean, this is not anywhere near our bottlenecks, so. Yeah. I mean, absolutely. I mean, I think there are all these different, what should I say, that people have written. So you can talk in JSON and, you know, at the last minute it sort of becomes XML. Yeah. So that's always an option. Yeah. I mean, I think at this point there's a lot of investment already in XML in terms of, you know, other servers. But we could definitely slowly phase it out. Yeah. Sorry, there are two communications going on. Sorry. I'm sorry. I think we need to prevent the number of conditions that are going on. Yeah. Sorry. What was your question? Okay. I mean, I don't know. So we're talking to Facebook, why X and PP? We haven't really looked into that. I mean, the thing is that we want to talk to several Java servers. So again, sorry, not a question. I know the answer. I mean, pretty much anything you could send over it. The, the Bosch spec itself, it allows you to send data inside, has a body in which you can send any arbitrary data. So as long as you send, I mean, sending data to it, you should be fine. It's not specific to X and PP if that's what you meant. The, if you want to build something that sends different data, you'll have to replace essentially these two pieces. So you can convert whatever you get over here to your custom protocol. Every time data comes in. So we've got a couple of plugins that we're using right now. So we've got plugins that sort of monitor, you know, for example, how many requests we've got going on and so on. We've got plugins that customize the protocol for us. So for example, we really wanted to speed up login. So what we did is that, you know, when our clients send a specific packet, we intercept that, prevent it from going forward, and then send a whole stream of packets that, you know, do the whole login authorization process and send it back. Yeah. So I mean, our, our plugin over here essentially just prevents the packet from going forward, sends whatever it wants and back. I didn't follow your question. Could you repeat that? Okay. I mean, you could do it, but I don't see the. I mean, there's nothing preventing us from doing it right now. The only thing is, as long as node is single thread, it doesn't really matter. If you're running multiple instances of node, you know, that's something we could do. If you're using the threads, right? I mean, there are all these libraries like step.js, float.js and so on. Yeah. I mean, in our case, that wasn't the problem. So what I was talking about is that, you know, sometimes you said the event pipe allows us to prevent packets from going forward, right? You want fire new, completely new events. So I want to pretend that the client is logging in and doing a bunch of things. And that's one thing. Similarly, we have a plugin that, you know, pushes to read this for, because you want to push based stuff to our mobile clients. We've got something that sends email. I mean, plugins that do various things that are listening for events and know that this is where they should interfere. So for example, if I'm unable to deliver a message to a client, I might send an email to that guy. I mean, you can read his work just as a queue. So this bot station may be server whenever to seek the message. And the client will just make it from it. So it's not even to push the message to the client. If you see what the server is doing, yes. On the other side, there's a push handle that subscribes that basically blocks messages from the queue and just pushes it out to your iPhone, push handle or whatever. Thanks. I think that's about it. Any questions remaining? All right, let's end early.