A story about Node.js and Azure WebApps
With the first Microsoft open source conference happening next 5th of April 2017 in Lisbon (https://msoscamp.io/) and being powered by Bright Pixel, I thought it was a good idea to share my recent experience with Azure, which I named it to myself as some kind of a return to Windows! Yes, after a few years working entirely with *nix systems and being more and more involved with the Node.js ecosystem, I made a service to interoperate with a classic Microsoft stack, with Windows, C# and ASP.Net, MSSQL, deployed within Azure.
Microsoft is changing, and in my opinion, in the right direction. For nearly two decades Microsoft ignored open source, but it was exactly those open technologies which accelerated the Internet evolution and today’s most used platforms. It’s on the web and cloud services where the Internet business is nowadays. With the new CEO Satya Nadella, Microsoft moved forward, embraced open source, continued with cloud services and pushed cloud platforms even further, doing changes to continue doing what Microsoft did and does very well: provide excellent tools and support to the developer community.
This article is not a benchmark neither a comparison with other platforms. It’s a story about the experience I had deploying and integrating a Node.js service, configuration which I know well how it behaves in a Linux environment, but now it needs to work in a Windows environment, and Microsoft development tools too. At this point I had to try and step back, giving up on my preferred production environments and use the ones the team is used to, understand where the team has more proficiency, learn and choose the best approach to achieve the number one rule in a development team: to ensure that everyone knows how, why and what is being done, how to support and extend the functionality and how to integrate it in the current platform configuration.
Microsoft Azure isn’t the first technical choice when it comes to deploying non-Microsoft technologies. However, the current pricing — especially if you have a bizspark plan — the support and the good path Microsoft started to follow a few years ago, encouraged us to give a try.
Recently, in a Node.js project, I worked with a Microsoft team deploying to Azure. Let me tell you this: It was a very very nice experience, even for a guy who’s only worked with Linux for the last few years.
The challenge and back to Windows
The project was a cloud storage solution with extra security features, based on real-time communication to share and revoke access to the content. The communications between the server and the clients use multiple approaches in order to ensure that at least one works, giving the user the full control over their own content. One of those approaches uses websockets, implemented with SignalR, a library which provides a nice abstraction for them. However, the challenge is indeed to implement another websockets interface, this time using Socket.io, which is an implementation written in JS and served with Node.js, commonly deployed in Linux environments. My job was to implement the server and add support to the clients. The current application core is based on an HTTP API built with ASP.net, where all the clients are connected, a typical API-centric architecture.
For me this was an excellent challenge for two main reasons; Firstly because I was away from the Microsoft ecosystem for a long time and secondly because it was an excellent team challenge. As a team we need to find a way to get it done, integrate and deploy it with the current application stack. Being working entirely with Linux for the last few years, lots of questions started to pop in my head immediately:
- How do I deploy a Node.js service on Windows?
- Yes, I can do a Socket.io with Node.js service, but can I implement the clients on the Windows base code?
- How to handle a continuous integration approach in the current configuration?
- How can I scale my app when the moment to do it arrives?
My experience told me to only worry about those questions at the proper time. First I have a job to do, using a Windows 10 environment and Visual Studio 2015. Yes, after four years without opening Visual Studio, I did it. Surprisingly, the basics are still the same and I started to fill my answers very quickly.
To build a Node.js based service using Visual Studio 2015, there is an extension that adds all the project generators needed to integrate with the Microsoft stack, doing a great job of glueing Internet Information Services (IIS) with the Node.js ecosystem using iisnode, handling the npm modules, environment variables, and the classic great Visual Studio debugger! You can check this extension here: https://www.visualstudio.com/vs/node-js/.
A few days after, the service was ready to deploy in a staging environment. This was the moment I was most curious about, because I still had some doubts on how to deploy it, in order to get all the team comfortable with the server configuration. However, just as a proof of concept, I setup up a Linux server running a pretty standard Node.js environment using the PM2 daemonizer and with Nginx serving as a reverse proxy for HTTP, HTTPs (using a let’s encrypt certificate) and WebSockets. It worked, but the environment is completely separate from the main application core, which is running on an IIS application server on Azure WebApps.
For as much as I liked the idea to push the team to use Linux, just to have the tux on the stack, at the same time I knew that it was a terrible idea in terms of productivity, and this was the moment the team started to work in order to find the most productive, cost-effective and scalable solution.
The Node.js options within Azure
Apart from the classic virtual machines, Azure started to offer a few platform-as-a-service (PaaS) solutions like Amazon, Heroku and others already did. This kind of cloud services is a pretty straight forward way to accelerate the deployment process, usually well integrated with continuous integration solutions and easy to scale too.
The PaaS solution which we found fitted best with the Node.js service was WebApps. This service is part of Azure App, a pre-configured Windows environment that supports a few technologies, such as ASP.NET, Node.js Java, PHP, Python or Go, with multiple runtime versions available out of the box. More than the languages supported, the features I valued the most in this project and team context were the seamless integrations with Visual Studio for deployment, easy scalability and having HTTPS included. But not everything is perfect with Azure WebApps and I found a few issues and limitations when using it with Node.js. The greatest limitation is actually Internet Information Services (IIS).
The WebApp details that matter
IIS is not the most loved HTTP and application server in the web development community. It’s hard to configure and it only runs on Windows. Until the moment ASP.NET Core came out, the only way to use .Net HTTP applications outside of Windows is by using the Mono framework, and the features are not the same between Mono and ASP.NET Core.
Enabling IIS and Node.js to work together, the iisnode module handles the application’s lifetime and takes care of node clustering, logging, application updates, etc. However, there was a huge limitation, one which particularly affects the service I made.
“App Service Web Apps is a fully managed compute platform that is optimized for hosting websites and web applications. This platform-as-a-service (PaaS) offering of Microsoft Azure lets you focus on your business logic while Azure takes care of the infrastructure to run and scale your apps.”
IIS and iisnode can’t do sticky sessions easily. After a long research, there was a way to do, it but looked like a hack and we decided to give up. Sticky sessions are crucial to use the socket.io library on the server, if you want to use node clustering. The initial client handshake needs multiple requests, and those requests should target the same server. The socket.io library doesn’t provide a way to do a cluster aware handshake, so we decided to leave it like that. Mainly because there was another way to do it: by spinning up a second WebApp instance and limiting each instance to use only one CPU core configuration (after all, it was useless to use more CPU cores without clustering). By doing that, the sticky sessions worked like a charm, as they’re handled by IIS instead of iisnode. This was not a huge problem because of a nice characteristic about the WebApps pricing:
- Basic instance 1 core, 1.75GB RAM: 0.08/ Hr
- Basic instance 2 core, 3.50GB RAM: 0.15/ Hr
- Basic instance 4 core, 7GB RAM: 0.30/ Hr
(Not a surprise because Microsoft knows how to price their products.)
In sum, it’s the same price to use multiple 1-CPU machines or just one 2-CPU machine. This give us the ability to scale horizontally too, which is always welcome in terms of service uptime.
Have a try with the online calculator: https://azure.microsoft.com/en-us/pricing/calculator/
At this moment we had a few problems solved:
- Deploy process, by using the Visual Studio integration, just click to deploy.
- Scale up, by spinning up extra WebApp instances, having extra service uptime and sticky sessions at the same time.
A few important questions answered
There were just a few details and features still remaining to be detailed, the ones that could encourage you, as a Node.js developer, to try Azure.
And if I don’t run Windows or use Visual Studio?
There’s a good command line interface which can be setup to manage the server configuration and deployments. Those deployments are made in a Heroku style and support two-factor authentication on your azure account.
And how about logging? How can I debug my app without the Visual Studio remote debugging tools, like I’m used to on Linux?
Use the online console. But frankly, it’s neither good nor easy to configure. My service had HTTP and websocket interfaces, but the log showed some random requests to the HTTP interface assuming it was a standard web page. The console sometimes stops giving output all of sudden: my recommendation is to integrate logging with a platform you trust.
How to use the other services provided by Azure, such as Service Bus, SQL Database, storage, etc.?
With Node.js you should use the Azure npm module. It’s pretty well made, documented and supported. I was able to implement cross application messaging with Azure Service Bus (pubsub mode) within an afternoon.
Is the performance good?
Honestly, I didn’t measure it, but it’s stable. I got the service to remain up without a restart for a few days in a row without any problems, except for deployments.
- Documentation is one of the best you can find.
- The Azure Node.js library.
- The seamless integration with Visual Studio.
- The command line interface.
- Continuous integration option, when the repos are based on Git.
- The logging is a mess, you should setup you own platform.
- The iisnode module has some limitations and the community around it is still small.
- It’s not the cheapest Node.js cloud platform.
My overall experience with Azure was good. Microsoft knows how to keep a developer happy and, apart from some things, my overall evaluation is positive.
Feel free to share your thoughts about the young Microsoft open source community below.