Microsoft Internet Information Services is one of the oldest web server platforms. Initially launched in 1995, it has been regularly updated with Windows Server. However, it’s been a while since the last major release, when IIS 10 Version 1809 was released in November 2018. Although Windows Server 2022 added support for QUIC and TLS 1.3, the core web server platform did not change.
Meanwhile, Microsoft has been quietly developing two alternative web server platforms as part of .NET, with a focus on delivering modern dynamic web applications. The first of these, Http.sys is a Windows-only server, ideal for running Windows-hosted ASP.NET Core applications at scale. The second, Kestrel, is the default ASP.NET Core web server and runs on all .NET Core platforms, including macOS. It’s designed to work behind load balancers like Nginx, as well as support modern web technologies like gRPC.
Kestrel is a great option for anyone building .NET web applications. It’s a relatively lightweight server compared to IIS, and since it’s cross-platform, it simplifies choosing a hosting platform. It is also suitable as a development tool, running on desktop hardware for testing and experimentation. HTTPS, HTTP/2, and a pre-release version of QUIC are supported, so your code is future-proof and will run securely.
Server installs as part of ASP.NET Core and is the default for sites that are not explicitly hosted by IIS. You don’t need to write any code to run Kestrel, beyond using the familiar
WebApplication.CreateBuilder method. Microsoft designed Kestrel to work with minimal configuration, either by using a settings file created when you use
dotnet new to set up an application scaffold or when creating a new application in Visual Studio.
Applications can configure Kestrel using the APIs in
WebApplicationBuilder, for example, by adding additional ports. Since Kestrel doesn’t run until your ASP.NET Core code is running, it’s a relatively easy way to make server configuration dynamic, with any changes just requiring a few lines of code. Similarly, you can add a new endpoint URL from the
dotnet run command or by modifying the command of your application
appsettings.json case. Alternatively, an ASP.NET Core environment variable can be set to manage the ports used. This flexibility makes Kestrel surprisingly easy to manage; you just choose the method that best fits your code.
Other options control the IP addresses on which a server listens for a connection, with the ability to listen on all available interfaces. If you work with HTTPS and need to test an application before putting it into production, Kestrel comes with a built-in test certificate to help you get started. This is installed as part of the ASP.NET Core SDK and can be managed from the
dotnet command line tool. Once in production, use the various configuration tools to select an appropriate certificate.
With Unix socket support, Kestrel is compatible with most load balancers, including Nginx. This makes it ideal for use in containers, whether on Linux or in a Windows container. Here, the Unix sockets support will allow you to add networking and security features to your code through a service mesh.
Customize your server, your way
Having a programmatically configurable web server is useful; you can add features as needed. For example, a production server can run with minimal logging. If problems arise, you can quickly configure Kestrel to add other logging providers to get more detailed operations. Other options include adding support for other services, for example, serving static content from a filesystem.
There are many options in ASP.NET Core for supported services, so you can extend beyond the default minimum API configuration, for example, by adding session management tools or caching some answers. It’s important to remember that adding new services adds more APIs to your server, which expands the attack surface. So only add features that you know you will use and that you know will be protected by your security platform.
Because Kestrel is highly customizable, you can manage supported HTTP verbs when accepting requests from browsers, as well as manage how your server responds to specific URI structures. Here you can take advantage of .NET primitives such as lambdas to parse data and use it in your applications, reducing the complexity of your code by offloading functionality to a server. This can make it easier to use URI encoding to manage application state, using routes to capture parameters in a URI. This way, Kestrel and ASP.NET can build and run single-page web applications, using the URI structure to determine what content is served to users.
Microsoft has developed a flexible and powerful web server that is a useful alternative to IIS for ASP.NET applications. Leveraging its minimal API approach, very little code is required to build a web server that can use routes and parameters to serve static content alongside ASP.NET Core functionality, exactly what is needed to build modern applications that can scale in the cloud. native containers.
How Microsoft replaced IIS with Kestrel
As always, it’s interesting to see what Microsoft is doing with its own tools. Kestrel recently partnered with the open-source .NET reverse proxy YARP to replace the underlying web platform in Azure App Services, a process described as “a heavyweight”. An interesting blog post detailed the process used to manage the migration, a process worth looking into if you plan to do the same with your own apps and services.
Although Azure App Services has the added demand of being a massively scalable multi-tenant platform, there are lessons in Microsoft’s migration that can apply to any move to Kestrel. It’s not the first service to make this change: Bing, Azure Active Directory and Dynamics 365 already use the same server.
The scale of Azure App Services is huge, even for hyperscale services like Azure. It currently supports over 160 billion HTTP requests per day and hosts over 14 million domain names. The underlying architecture is typical of cloud-scale services, with the platform behind a set of load balancers and with App Service code running on a set of workers, delivered through a web server. Overall, that means over 200,000 cores running web servers.
Before the update it worked on IIS and HTTP.sys. By switching to Kestrel and YARP, Microsoft could offer its users a broader set of HTTP protocols, improve its secure connection options, and still allow developers to use their choice of application platforms.
The process of migrating a front-end service that works with traditional browsers as well as REST API and gRPC clients revealed some issues with Kestrel that have since been resolved, making it more suitable for user-facing applications. Perhaps the most interesting change resulted in less strict Kestrel behavior. Originally written to conform to the HTTP specification, it rejected requests that included newline characters at the start of a line. The Kestrel team has now relaxed their conformance, and newer versions now accept this class of request.
Moving to a new platform from a platform that has been running since the early days of Azure gives us some interesting benchmarks: throughput has increased by almost 80% for HTTP requests standard. This results in a significant reduction in CPU usage across the entire fleet of Front End Services hosts, which the team continues to monitor in hopes of eventually reducing the number of cores they use. , saving both cost and data center resources.
Because Kestrel is cross-platform, the same code can now support Linux workloads, allowing Azure to remove the Nginx servers that provided Linux workload front ends. Having the same infrastructure for Linux and Windows should reduce management overhead, with a common code base for the service and a common feature set. As Kestrel and YARP update, new features will be available to all Azure App Service users, not just an OS-specific subset.
The work Microsoft has done to deliver Kestrel and YARP in Azure App Service will benefit everyone who uses Kestrel. Putting it at the core of one of Azure’s most demanding platforms will quickly reveal edge cases that might not be visible to ASP.NET Core, at least not without requiring significant debugging.
It’s a win-win scenario for Kestrel and ASP.NET Core, which makes it more likely that your next project will target Kestrel rather than the aging IIS. The result should be web servers that are easier to configure and manage and that run on most common server platforms or in containers, without the trade-off between simplicity and security that is too often an issue when large-scale execution.
Copyright © 2022 IDG Communications, Inc.