The evolution of software development from monolithic on-premises applications to containerized microservices running in the cloud took a major step forward last summer with the release of .NET Core 2. As I wrote in the “Understanding the Momentum Behind .NET Core,” the number of developers using .NET Core recently passed the half million mark. Yet in the rush to adoption many developers have encountered a speed bump. It turns out the changes that make .NET Core so revolutionary create new challenges for application performance monitoring.
Unlike .NET apps that run on top of IIS and are tied to Windows infrastructure, microservices running on .NET Core can be deployed anywhere. The customers I’ve spoken with are particularly interested in deploying microservices on Linux systems, which they believe will deliver the greatest return on investment. But the flexibility comes at cost.
When operations engineers move .NET applications to .NET Core they are seeking fully functional, performant environments that are designed for a microservice. What they are finding is that the .NET Core environment requirements vary substantially from the environments that the full framework runs on. While .NET Core’s independence from IIS and Windows machines provides flexibility, it also means that some performance tools for system metrics may no longer be relevant.
Engineers who are used to debugging apps in a traditional Windows environment find that valuable tools like Event Tracing for Windows (ETW) and performance counters are not consistently available. For example, an on-premises Windows machine allows you to read performance counters while Azure WebApps on Windows only provides access to application-specific performance counters. Neither ETW nor performance counters are available on Linux, so if you want to deploy an ASP.NET Core microservice on Linux you will need to modify your method of collecting system-level data.
In creating .NET Core and the ASP.NET Core framework Microsoft made improving performance a top priority. One of the biggest changes was replacing the highly versatile but comparatively slow IIS web server with Kestrel, a stripped-down, cross-platform web server. Unlike IIS, Kestrel does not maintain backwards compatibility with a decade-and-half of previous development and is specifically suited to the smaller environments that characterize microservices development and deployment. Open-source, event-driven, and asynchronous, Kestrel is built for speed. But the switch from IIS to Kestrel is not without tradeoffs. Tools we relied on before like IIS Request Failed logging don’t consistently work. The fact is, Kestrel is more of an application server than a web server, and many organizations will want to use a full-fledged web server like IIS, Apache, or Nginx in front as a reverse proxy. This means engineers have to now familiarize themselves with the performance tools, logging, and security setup for these technologies.
Beyond monitoring web servers, developers need performance metrics for the entire platform where a microservice is deployed—from Azure and AWS to Google Cloud Platform and Pivotal Cloud Foundry, not to mention additional underlying technologies like Docker. The increase in platforms has a tendency to add up to an unwelcome increase in monitoring tools.
At the same time, the volume, velocity, and types of data from heterogeneous, multi-cloud, microservices-oriented environments is set to increase at exponential rates. This is prompting companies who are adopting .NET Core and microservices to take a hard look at their current approach to application monitoring. Most are concluding that the traditional patchwork of multiple tools is not going to be up to the task.
While application performance monitoring has gotten much more complex with .NET Core, the need for it is even more acute. Migrating applications from .NET without appropriate monitoring solutions in place can be particularly risky.
One key concern is that not all .NET Framework functionality is available in .NET Core, including .NET Remoting, Code Access Security and AppDomains. Equivalents are available in ASP.NET Core, but they require code changes by a developer. Likewise, HTTP handlers and other IIS tools must be integrated into a simplified middleware pipeline in ASP.NET Core to ensure that the logic remains part of an application as it migrated from .NET to .NET Core.
Not all third-party dependencies have a .NET Core-compatible release. In some cases, developers may be forced to find new libraries to address an application’s needs.
Given all of the above, mistakes in migration are possible. There may be errors in third-party libraries, functionality may be missing, and key API calls may cause errors. Performance tools are critical in helping this migration by providing granular visibility into the application and its dependencies. Problems can thus be identified earlier in the cycle, making the transition smoother.
AppDynamics had been tackling the challenges outlined in this post for more than a year. A beta release of support for .NET Core 2.0 on Windows became available in January, and we’ll have more news going forward.
Please stay tuned for my next blog post about AppDynamics’ approach to app monitoring with .NET Core.