建立一個.Net Core Web Api的專案,取名API Gateway
在Models目錄底下簡單建一個用來標示服務的class 只包含服務名字跟位置
namespace APIGateway.Models
{
public class MicroService
{
public string Name { get; set; }
public string Location { get; set; }
}
}
加入一個使用web api用以接受Service註冊跟註銷的Controller
using APIGateway.Models; //記得引入Models
namespace APIGateway.Controllers
{
[Produces("application/json")]
[Route("api/ServiceRegistry")]
public class ServiceRegistryController : Controller
{
static List<MicroService> serviceList = new List<MicroService>() {
new MicroService() { Name="API Gateway", Location="http://localhost:2324" }
};
// GET: api/ServiceRegistry
[HttpGet]
public IEnumerable<MicroService> Get()
{
return serviceList;
}
// POST: api/ServiceRegistry
[HttpPost]
public void Post([FromBody]MicroService service)
{
serviceList.Add(service);
}
// DELETE: api/ServiceRegistry/{serviceName}
[HttpDelete("{serviceName}")]
public void Delete(string serviceName)
{
serviceList.Remove(serviceList.First(s => s.Name == serviceName));
}
}
}
再建立一個.Net Core Web Api的專案, 取名ProductService
接著為了要在Service的啟動跟停止發request給ServiceRegistryController註冊跟註銷服務
需要在StartUp.cs寫一些code,
在Configure方法加入參數IApplicationLifetime appLifetime,接著利用appLifeTime掛載host啟動跟停止時要實施的方法:
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopped.Register(OnStopped);
在OnStarted跟OnStopped分別發送request給ServiceRegistry在開始時註冊服務,取消時註銷服務
另外因為找不到如何手動關閉 ProductService我又加了一段code讓他自己關閉(利用applifetime.StopApplication())
app.Use(next =>
{
return async (context) =>
{
await context.Response.WriteAsync("Application will shut down");
await Task.Delay(10000);
appLifetime.StopApplication();
};
});
public class Startup
{
IServerAddressesFeature serverAddressesFeature;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime.
Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
}
// This method gets called by the runtime.
Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
IApplicationLifetime appLifetime)
{
//serverAddressesFeature = app.ServerFeatures.Get<IServerAddressesFeature>();
//Get Kestrel Uri
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
appLifetime.ApplicationStarted.Register(OnStarted);
appLifetime.ApplicationStopped.Register(OnStopped);
app.Use(next =>
{
return async (context) =>
{
await context.Response.WriteAsync("Application will shut down");
await Task.Delay(10000);
appLifetime.StopApplication();
};
});
}
private void OnStarted() {
Console.WriteLine("Starting");
using (HttpClient client = new HttpClient()) {
//string data = serverAddressesFeature.Addresses.FirstOrDefault().ToString(); //Kestrel
string IISExpressIP = "http://localhost:4147";
string json = JsonConvert.SerializeObject(new{ Name="ProductService",
Location=IISExpressIP });
HttpContent contentPost = new StringContent(json, Encoding.UTF8,
"application/json");
HttpResponseMessage response =
client.PostAsync("http://localhost:2343//api/ServiceRegistry",
contentPost).Result;
}
}
private void OnStopped() {
using (HttpClient client = new HttpClient()) {
string Uri = "http://localhost:2343/api/ServiceRegistry";
string IISExpressIP = "http://localhost:4147";
var service = new { Name = "ProductService", Location = IISExpressIP };
string json = JsonConvert.SerializeObject(service);
HttpContent contentPost = new StringContent(json,
Encoding.UTF8, "application/json");
string requestUri = $"{Uri}/{service.Name}";
HttpResponseMessage response = client.DeleteAsync(requestUri).Result;
}
Console.WriteLine("Stopped");
}
}
```
利用ctrl-F5啟動API Gateway專案,
在ProductService中設置中斷點在private void OnStopped()
利用F5啟動ProductService,
停在中斷點時利用Postman發送get給http://localhost:2343/api/Registry
會看到ProductService已經被註冊
[
{
"name": "Initial",
"location": "http://localhost:2324"
},
{
"name": "ProductService",
"location": "http://localhost:4147"
}
]
F5繼續,直到程式中止,利用Postman發送get給http://localhost:2343/api/Registry
會看到ProductService已經被註銷
[
{
"name": "Initial",
"location": "http://localhost:2324"
}
]
# 這邊重點是我們可以利用appLifetime來處理服務的啟動或是結束事件。
這個簡單的Service Registry只是練習.Net Core下的產物, 實際上的例子多半會用第三方的套件像是ZooKeeper、Netflix Eureka來實現Service registry
另外有一個有問題的地方是,本來嘗試要自動取得ProductService的Uri,但發現只能取得Kestrel的Uri,
而無法取得最終IIS Express的Uri,所以只好先hard code了, 之後找到解法再來修正
Merry Christmas!
版主你好 因為我是用.net core 6實作 想詢問關於productService啟動時 會出現以下錯誤
請問是否是因為我Url設定錯誤導致的呢?
請問版主的 HttpResponseMessage response = client.PostAsync("http://localhost:2343//api/ServiceRegistry",contentPost).Result;
的Url 是對照 專案api gateway ip Url嗎?
另外請問 ProductService 這個專案controller有新增RegistryController.cs嗎?