
2024年在線市場(chǎng)平臺(tái)的11大最佳支付解決方案
網(wǎng)關(guān)其實(shí)就是將我們寫(xiě)好的API全部放在一個(gè)統(tǒng)一的地址暴露在公網(wǎng),提供訪問(wèn)的一個(gè)入口。在 .NET Core下可以使用Ocelot
來(lái)幫助我們很方便的接入API 網(wǎng)關(guān)。與之類似的庫(kù)還有ProxyKit
,微軟也發(fā)布了一個(gè)反向代理的庫(kù)YARP
。
關(guān)于網(wǎng)關(guān)的介紹不多說(shuō)了,網(wǎng)上文章也挺多的,這些都是不錯(cuò)的選擇,聽(tīng)說(shuō)后期Ocelot
將會(huì)使用YARP
來(lái)重寫(xiě)。本篇主要實(shí)踐一下在.NET Core環(huán)境下使用Ocelot
。
先創(chuàng)建幾個(gè)項(xiàng)目用于測(cè)試,創(chuàng)建兩個(gè)默認(rèn)的API項(xiàng)目,Api_A和Api_B,在創(chuàng)建一個(gè)網(wǎng)關(guān)項(xiàng)目Api_Gateway,網(wǎng)關(guān)項(xiàng)目可以選擇空的模板。
現(xiàn)在分別在Api_A和Api_B中寫(xiě)幾個(gè)api,將默認(rèn)的WeatherForecastController
中返回模型WeatherForecast
添加一個(gè)字段Source,用于區(qū)分是哪個(gè)API返回的數(shù)據(jù)。
using System;
namespace Api_A
{
public class WeatherForecast
{
public string Source { get; set; } = "Api_A";
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}
using System;
namespace Api_B
{
public class WeatherForecast
{
public string Source { get; set; } = "Api_B";
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}
直接使用WeatherForecastController
默認(rèn)方法,在路由中添加api前綴。
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Api_A.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
}
}
}
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Api_B.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class WeatherForecastController : ControllerBase
{
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
var rng = new Random();
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateTime.Now.AddDays(index),
TemperatureC = rng.Next(-20, 55),
Summary = Summaries[rng.Next(Summaries.Length)]
}).ToArray();
}
}
}
再分別在Api_A和Api_B中添加兩個(gè)控制器:ApiAController、ApiBController,然后加上幾個(gè)簡(jiǎn)單的restful api。
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Api_A.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ApiAController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
[HttpGet("{id}")]
public string Get(int id)
{
return $"Get:{id}";
}
[HttpPost]
public string Post([FromForm] string value)
{
return $"Post:{value}";
}
[HttpPut("{id}")]
public string Put(int id, [FromForm] string value)
{
return $"Put:{id}:{value}";
}
[HttpDelete("{id}")]
public string Delete(int id)
{
return $"Delete:{id}";
}
}
}
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
namespace Api_B.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ApiBController : ControllerBase
{
[HttpGet]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
[HttpGet("{id}")]
public string Get(int id)
{
return $"Get:{id}";
}
[HttpPost]
public string Post([FromForm] string value)
{
return $"Post:{value}";
}
[HttpPut("{id}")]
public string Put(int id, [FromForm] string value)
{
return $"Put:{id}:{value}";
}
[HttpDelete("{id}")]
public string Delete(int id)
{
return $"Delete:{id}";
}
}
}
方便查看接口,這里添加一下swagger
組件,這樣我們Api_A和Api_B項(xiàng)目分別就有了6個(gè)接口。
接著打包docker鏡像,放在docker中運(yùn)行這兩個(gè)api項(xiàng)目。這一步可以用任何你熟悉的方式,run起來(lái)即可。
docker build -t api_a:dev -f ./Api_A/Dockerfile .
docker build -t api_b:dev -f ./Api_B/Dockerfile .
build成功后,指定兩個(gè)端口運(yùn)行api項(xiàng)目。
docker run -d -p 5050:80 --name api_a api_a:dev
docker run -d -p 5051:80 --name api_b api_b:dev
Api_A指定了5050端口,通過(guò) http://localhost:5050/swagger打開(kāi)可以看到swagger文檔界面,Api_B指定了5051端口,通過(guò) http://localhost:5051/swagger打開(kāi)可以看到swagger文檔界面,這樣就大功告成了,接下來(lái)才是重點(diǎn)將兩個(gè)api項(xiàng)目配置到Api_Gateway網(wǎng)關(guān)項(xiàng)目中。
在網(wǎng)關(guān)項(xiàng)目Api_Gateway中都添加Ocelot
組件包。
Install-Package Ocelot
Ocelot
中最關(guān)鍵的就是配置路由信息,新建一個(gè)ocelot.json
配置文件,將我們的兩個(gè)API接口匹配規(guī)則放進(jìn)去。
{
"Routes": [
//ApiA
{
"DownstreamPathTemplate": "/api/WeatherForecast",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5050
}
],
"UpstreamPathTemplate": "/ApiA/WeatherForecast",
"UpstreamHttpMethod": [ "Get" ]
},
{
"DownstreamPathTemplate": "/api/ApiA",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5050
}
],
"UpstreamPathTemplate": "/ApiA",
"UpstreamHttpMethod": [ "Get", "POST" ]
},
{
"DownstreamPathTemplate": "/api/ApiA/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5050
}
],
"UpstreamPathTemplate": "/ApiA/{id}",
"UpstreamHttpMethod": [ "Get", "Put", "Delete" ]
},
//ApiB
{
"DownstreamPathTemplate": "/api/WeatherForecast",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5051
}
],
"UpstreamPathTemplate": "/ApiB/WeatherForecast",
"UpstreamHttpMethod": [ "Get" ]
},
{
"DownstreamPathTemplate": "/api/ApiB",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5051
}
],
"UpstreamPathTemplate": "/ApiB",
"UpstreamHttpMethod": [ "Get", "POST" ]
},
{
"DownstreamPathTemplate": "/api/ApiB/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5051
}
],
"UpstreamPathTemplate": "/ApiB/{id}",
"UpstreamHttpMethod": [ "Get", "Put", "Delete" ]
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:44335"
}
}
關(guān)于配置文件中的各項(xiàng)具體含義,可以參考官方文檔中的介紹。主要就是將DownstreamPathTemplate模板內(nèi)容轉(zhuǎn)換為UpstreamPathTemplate模板內(nèi)容進(jìn)行接口的訪問(wèn),同時(shí)可以指定HTTP請(qǐng)求的方式等等。GlobalConfiguration中的BaseUrl為我們暴漏出去的網(wǎng)關(guān)地址。
設(shè)置好ocelot.json
后,需要在代碼中使用它,在Program.cs
中添加配置文件。
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
namespace Api_Gateway
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
config.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
在Startup.cs
中使用Ocelot
。
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
namespace Api_Gateway
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
app.UseOcelot().Wait();
}
}
}
完成以上操作后,我們?cè)囍フ{(diào)用接口看看能否正確獲取預(yù)期數(shù)據(jù)。
curl -X GET "https://localhost:44335/ApiA"
curl -X GET "https://localhost:44335/ApiB"
curl -X POST "https://localhost:44335/ApiA" -H "Content-Type: multipart/form-data" -F "value=ApiA"
curl -X POST "https://localhost:44335/ApiB" -H "Content-Type: multipart/form-data" -F "value=ApiB"
curl -X GET "https://localhost:44335/ApiA/12345"
curl -X GET "https://localhost:44335/ApiB/12345"
curl -X PUT "https://localhost:44335/ApiA/12345" -H "Content-Type: multipart/form-data" -F "value=ApiA"
curl -X PUT "https://localhost:44335/ApiB/12345" -H "Content-Type: multipart/form-data" -F "value=ApiB"
curl -X DELETE "https://localhost:44335/ApiA/12345"
curl -X DELETE "https://localhost:44335/ApiB/12345"
curl -X GET "https://localhost:44335/ApiA/WeatherForecast"
curl -X GET "https://localhost:44335/ApiB/WeatherForecast"
可以看到,兩個(gè)項(xiàng)目中的接口全部可以通過(guò)網(wǎng)關(guān)項(xiàng)目暴露的地址進(jìn)行中轉(zhuǎn),是不是很方便?
本篇只是簡(jiǎn)單的應(yīng)用,對(duì)于Ocelot
的功能遠(yuǎn)不止于此,它非常強(qiáng)大,還可以實(shí)現(xiàn)請(qǐng)求聚合、服務(wù)發(fā)現(xiàn)、認(rèn)證、鑒權(quán)、限流熔斷、并內(nèi)置了負(fù)載均衡器,而且這些功能都是只需要簡(jiǎn)單的配置即可完成。就不一一描述了,如有實(shí)際開(kāi)發(fā)需求和問(wèn)題,可以查看官方文檔和示例。
本文章轉(zhuǎn)載微信公眾號(hào)@一線碼農(nóng)聊技術(shù)
2024年在線市場(chǎng)平臺(tái)的11大最佳支付解決方案
完整指南:如何在應(yīng)用程序中集成和使用ChatGPT API
選擇AI API的指南:ChatGPT、Gemini或Claude,哪一個(gè)最適合你?
用ASP.NET Core 2.1 建立規(guī)范的 REST API — 緩存和并發(fā)
企業(yè)工商數(shù)據(jù)API用哪種?
2024年創(chuàng)建社交媒體帖子的最佳圖像工具API
2024年小型企業(yè)的7個(gè)最佳短信應(yīng)用API
用gin寫(xiě)簡(jiǎn)單的crud后端API接口
最新LangChain+GLM4開(kāi)發(fā)AI應(yīng)用程序系列(一):快速入門(mén)篇
對(duì)比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力
一鍵對(duì)比試用API 限時(shí)免費(fèi)