Introduction
In the previous articles of this series, we discussed how to build the API Gateway in ASP.NET Core.
And in this article, we will discuss service discovery module of Ocelot with Spring Cloud Eureka Server.
If you want to look at the previous articles of this series, please visit the links given below.
What is Service Discovery?
Service discovery is the automatic detection of devices and services offered by these devices on a computer network. A service discovery protocol (SDP) is a network protocol that helps accomplish service discovery. Service discovery aims to reduce the configuration efforts from users.
There are some types of service discovery we can use in Ocelot, such as Consul, Eureka, and so on. In this article, I will show you the usage with Eureka. Ocelot uses
Steeltoe to communicate with Eureka, which is an open source project that enables .NET developers to implement industry standard best practices when building resilient microservices for the cloud.
I will use version 7.1.0-unstable0011 of Ocelot to show you this feature.
Step 1
We are creating two API services at first. Just create the default ASP.NET Core Web API project. Before API gateway can discover our API Services, we need to register them in Eureka Server.
Add some configuration in
appsettings.json.
- "spring": {
- "application": {
- "name": "service-a"
- }
- },
- "eureka": {
- "client": {
- "serviceUrl": "http://192.168.0.107:8761/eureka/",
- "shouldFetchRegistry": true,
- "validateCertificates": false
- },
- "instance": {
- "port": 9001,
- "instanceId": "192.168.0.103:9001",
- "hostName": "192.168.0.103",
- "healthCheckUrlPath": "/api/values/healthcheck",
- "statusPageUrlPath": "/api/values/info"
- }
- }
Note
- Service-a is an important part that ocelot will use it to find out this service.
- ServiceUrl is the endpoint of the Eureka Server.
- For more information of each item, you can visit here.
Add some code to enable service discovery.
- public class Startup
- {
- public Startup(IConfiguration configuration)
- {
- Configuration = configuration;
- }
-
- public IConfiguration Configuration { get; }
-
- public void ConfigureServices(IServiceCollection services)
- {
- services.AddDiscoveryClient(Configuration);
- services.AddMvc();
- }
-
- public void Configure(IApplicationBuilder app, IHostingEnvironment env)
- {
- if (env.IsDevelopment())
- {
- app.UseDeveloperExceptionPage();
- }
-
- app.UseDiscoveryClient();
- app.UseMvc();
- }
- }
Here, I will use three API Services to show, two API services name service-a with different port (9001 and 9003), one API service name service-b.
Step 2
Create an APIGateway project. And add a json configuration file named ocelot.json.
- {
- "ReRoutes": [
- {
- "DownstreamPathTemplate": "/api/values",
- "DownstreamScheme": "http",
- "UpstreamPathTemplate": "/a",
- "UseServiceDiscovery": true,
- "ServiceName": "service-a",
- "UpstreamHttpMethod": [ "Get" ],
- "QoSOptions": {
- "ExceptionsAllowedBeforeBreaking": 3,
- "DurationOfBreak": 1000,
- "TimeoutValue": 5000
- },
- "FileCacheOptions": { "TtlSeconds": 15 },
- "LoadBalancerOptions": {
- "Type": "RoundRobin"
- }
- },
- {
- "DownstreamPathTemplate": "/api/values",
- "DownstreamScheme": "http",
- "UpstreamPathTemplate": "/b",
- "UseServiceDiscovery": true,
- "ServiceName": "service-b",
- "UpstreamHttpMethod": [ "Get" ],
- "QoSOptions": {
- "ExceptionsAllowedBeforeBreaking": 3,
- "DurationOfBreak": 1000,
- "TimeoutValue": 5000
- },
- "FileCacheOptions": { "TtlSeconds": 15 }
- }
- ],
- "GlobalConfiguration": {
- "RequestIdKey": "OcRequestId",
- "AdministrationPath": "/administration",
- "ServiceDiscoveryProvider": { "Type": "Eureka" }
- }
- }
There are some items we need to pay attention to.
For ReRoutes,
- Set UseServiceDiscovery to true;
- Set ServiceName to service's name that define in API service.
- Do not specify the DownstreamHostAndPorts
- Set type of LoadBalancerOptions to RoundRobin.
For GlobalConfiguration
Just specify the ServiceDiscoveryProvider. Set the type to Eureka. This is a very very important configuration to use Eureka!!
Turning to Program.cs, we need to enable Ocelot!!
- public class Program
- {
- public static void Main(string[] args)
- {
- BuildWebHost(args).Run();
- }
-
- public static IWebHost BuildWebHost(string[] args) =>
- WebHost.CreateDefaultBuilder(args)
- .UseUrls("http://*:9000")
- .ConfigureAppConfiguration((hostingContext, config) =>
- {
- config
- .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
- .AddJsonFile("ocelot.json")
- .AddEnvironmentVariables();
- })
- .ConfigureServices(s =>
- {
- s.AddOcelot();
- })
- .Configure(a =>
- {
- a.UseOcelot().Wait();
- })
- .Build();
- }
Step 3
Let's run up the Eureka Server.
As you can see, the Eureka Server is up but there are no instances available.
Note
For running the Eureka server in your computer, you can try the following steps.
- Install Java 8 JDK.
- Install Maven 3.x.
- Clone the Spring Cloud Samples Eureka repository. (https://github.com/spring-cloud-samples/eureka.git)
- Go to the eureka server directory (eureka) and fire it up with mvn spring-boot:run
Step 4
How can we register our services? Just run up our project! We will take
service-a for example.
After running up API service, we can find that
service-a is up in Eureka server!
Now, let's run the API Gateway. Unfortunatelly, at this time we can run up our API Gateway.
Based on the exception message, we forget to config the Eureka in the API Gateway project. Add the configuration in
appsettings.json.
- "spring": {
- "application": {
- "name": "service-gw"
- }
- },
- "eureka": {
- "client": {
- "serviceUrl": "http://192.168.0.107:8761/eureka/",
- "shouldRegisterWithEureka": false,
- "validateCertificates": false
- },
- "instance": {
- "port": 9000,
- "instanceId": "192.168.0.103:9000",
- "hostName": "192.168.0.103"
- }
- }
Run the API Gateway again. It runs well now.
Visit
service-a via API Gateway.
Visit
service-b via API Gateway which we do not run up yet.
There is no doubt that we cannot access
service-b.
After running up:
Visit again.
It can be accessed now.
At last, register another
service-a.
Visit service-a, sometimes you will get the result from 9001 and sometimes from 9003, because we use RoundRobin LoadBalancer.
And when we stop one of
service-a, we can still visit it, and it will not visit the break service.
Here is the source code you can find in my github page .
APIGatewaySDDemo
Summary
This article introduced the basic usage of service discovery with Eureka in Ocelot.
You can also use this feature with Consul.
I hope this helps you.