Recently Keyhole wrote the white paper “Predicting The Future Of Development.” The white paper recommends enterprises move away from the Monolithic-based architectures that “have been a common approach for the enterprise, where all application functionality is placed in a single deployable unit.”
Instead the recommendation is to move towards Single-Page Applications and Microservices that “breaks up functionality into smaller runtime elements that can be tested and deployed separately.”
The white paper also provides a good overview of the Microservices-based architecture and mentions several patterns and frameworks that have been defined and developed by companies that have successfully implemented the Microservice architecture style. I do not intend to rehash the points made in the white paper in this blog, so I encourage you to check out the white paper itself.
In this blog, I discuss a potential solution for how to begin implementing a Microservices architecture style within current Windows Server Enterprise environments. In this case, I also seek to structure in such a way to make it fairly easy to migrate toward the soon-to-come cloud offerings.
I feel it is important to also touch on the patterns Service Registry, Service Discovery, API Gateway, and Circuit Breaker, as well as the recommended frameworks Apache Zookeeper, https://netflix.github.io, and the ELK stack (Elasticsearch, Logstash, and Kibana). Reviewing those recommended frameworks you’ll quickly notice the subtle earthy undertones of a particular language. While our favorite brew can be hosted on a Windows Server, I wanted to explore what native tooling might be available within the Microsoft Ecosystem.
While my google-fu may have failed me, I was not able to find much of anything that currently exists for the Windows Enterprise that would match the functionality of the above-mentioned frameworks.
First let me go through the definitions of those patterns.
Service Registry - A service registry communicates when and if a service is available for use, and through a heartbeat mechanism, determines if a service is alive. Also, the registry contains the current location (server:port) of a deployed service.
Service Discovery - Other services can discover the location port/dns of a dependant service,
API Gateway - Server as an API gateway for an application user interface into application services. Service calls can be aggregated here to serve specific user interface functions, or just passed through in order to avoid having to use CORS. Also, load balancing, user identity authentication and authorization can be applied here.
Circuit Breaker - Since there could be many layers of service calls involved in an application, a failure of in one of them could cause a cascade of errors up the calling routes. The circuit break pattern captures failures and defines a threshold of failures within a specified time, and closes the circuit which immediately reports an error instead of attempting to repeatedly keep accessing the service.
The Soon-to-Come Future
Note that I used the phrase “currently exists” when I said that I was not able to find much of anything that currently exists for the Windows Enterprise that would match the functionality of the frameworks mentioned above.
Microsoft’s Azure platform has released the Azure Service Fabric in developer preview. This is Microsoft’s solution for quickly developing, hosting, and managing Microservice solutions. Mark Russinovich, CTO of Microsoft Azure, gave a great overview of this “high control” platform in his Azure Service Fabric Announcement.
One of the highlights from the article states that it “provides the foundational technology upon which we run our Azure core infrastructure and also powers services like Skype for Business, InTune, Event Hubs, DocumentDB, Azure SQL Database (across more than 1.4 million customer databases) and Bing Cortana.”
Service Fabric is not just a new service that Microsoft is offering, but it is “battle-hardened technology available for everyone use – not a version of what we use, but the exact technology we use ourselves.” Another facet of this offering, especially for the enterprise infrastructure folks, is the ability to deploy on-premise within an existing Windows Server 2012+ ecosystem.
But wait there’s more: the services that can be deployed into Service Fabric do not have to be part of the typical MS Stack. They are planning on offering support for other (even non-MS) languages and the Linux environment also. (See the node.exe reference in the example servicemanifest.xnml in Service Fabric Deploy Existing App and the diagram in the Service Fabric Overview.)
Please forgive that fanboy moment, but Service Fabric is a very exciting technology just around the corner. Definitely a technology platform to begin investigating for hosting your microservice solutions.
How to Prepare for the Future . . . Just Around the Corner
So the question still stands: how can the Windows Server Enterprise begin implementing the Microservices architecture style within their current environments? Secondly, can this be done in such a way to be fairly easy to migrate towards the soon-to-come cloud offerings?
This is the situation we find ourselves in with a current client of Keyhole Software. They want to move forward with the benefits of a Microservices-based architecture hosted on the investment they have already made with their on-premise hardware, but with an eye toward being able to move towards a hybrid environment of on-premise and cloud based hosting. The client is a perfect candidate for the Azure Service Fabric mentioned.
Enter WebAPI, Application Request Routing, and URL Rewrite
The solution we have chosen to implement develops WebAPI projects on top of Microsoft’s OWIN implementation Katana. This allows us to be able to host the services either within an IIS Server Website, individual Self-Hosted Window’s Services or console applications (which by the way can also be hosted in SF).
The only extra step we have taken is to define a fairly basic pattern we are calling InstantAPI that splits a WebAPI into 2 parts.
The first is a Host WebAPI Katana Project that does not contain any controller definitions, just the basics of one of the Katana hosting options. The second part creates separate API Module projects that are built as basic Class Library types. These projects only define the controller definitions and any supporting logic, without any hosting configuration.
This separation is possible through the Nuget package Microsoft.Web.Infrastructure. The benefit gained is the ability to configure one or more Host instances that can contain one or more API Module DLLs. This provides for an unbounded number of configurations across servers throughout the enterprise without the need to recompile. Plus this will also help to meet the requirement of being able to be hosted in the cloud, specifically thinking of Azure Service Fabric mentioned earlier though the use of the console application host.
Where did that service go?
Now that services are spread throughout the enterprise we are now presented with the dilemma of how to route requests to these services. A.K.A the Service Registry and Service Discovery patterns mentioned above.
Enter Application Request Routing (ARR), a Microsoft developed IIS extension working along side of the URL Rewrite extension. ARR allows you to define a Server Farm that can provide load balancing, health checks, fault tolerance, etc. Setting up health checks at regular intervals allows ARR to manage the viability of the service and disable routing to this service until the issue has been addressed. Meeting the need of the both the Service Registry and Circuit Breaker pattern.
The URL Rewrite extension is then used to redirect requests towards a specific server farm. For instance requests for api.example.com/api1 can route to one server farm and api.example.com/api2 can route to another. Meeting the Service Discovery pattern.
For example a routing pattern that could be implemented is: (see diagram)
- Create an API Gateway by using URL Rewrite rule to redirect requests from the Application domain into the API domain. (e.g. app.example.com/api/api1 can be redirected to api.example.com/api1 )
- Create a common domain name to be used by clients as the entry point into the ARR server (e.g api.example.com).
- Create domain names for each WebAPI Host instances (e.g host1.example.com, host2.example.com). ARR does allow routing based on ip address and port, but using domain names would help the system be more precise and understandable.
- Server Farms in ARR for each API Module. Then add the Host instance domains for those instance that contain the modules DLL.
- Configure the ARR Health Check to an endpoint specific to that module. This will allow ARR to manage individual modules even though they may be contained in the same WebAPI Host.
A Stop-Gap Solution
This option is not as dynamic as the service registration functionality of something like Eureka. But I believe it is a good solution for meeting the requirements of hosting within the Windows Server enterprise with the potential to move to a cloud or hybrid solution.
The one concern I have with this solution is how granular should a API Module be defined. The more granular a module, the modules you will end up within the application’s ecosystem. Which means the more Server Farms that will need to be created and managed within ARR.
The discussions we are having in-house are to make our API Modules more coarse, grouping similar endpoints into more functional services that share a bounded context. But I will leave that discussion for a later time.
— Jeff Hopper, [email protected]