<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          .NET Core 下的 API 網(wǎng)關(guān)

          共 10271字,需瀏覽 21分鐘

           ·

          2020-10-02 16:19

          網(wǎng)關(guān)介紹

          網(wǎng)關(guān)其實就是將我們寫好的API全部放在一個統(tǒng)一的地址暴露在公網(wǎng),提供訪問的一個入口。在 .NET Core下可以使用Ocelot來幫助我們很方便的接入API 網(wǎng)關(guān)。與之類似的庫還有ProxyKit,微軟也發(fā)布了一個反向代理的庫YARP

          關(guān)于網(wǎng)關(guān)的介紹不多說了,網(wǎng)上文章也挺多的,這些都是不錯的選擇,聽說后期Ocelot將會使用YARP來重寫。本篇主要實踐一下在.NET Core環(huán)境下使用Ocelot

          • Ocelot官網(wǎng):https://threemammals.com/ocelot
          • Ocelot文檔:https://ocelot.readthedocs.io
          • GitHub:https://github.com/ThreeMammals/Ocelot
          • Ocelot資源匯總:https://www.cnblogs.com/shanyou/p/10363360.html

          接入使用

          接口示例

          先創(chuàng)建幾個項目用于測試,創(chuàng)建兩個默認(rèn)的API項目,Api_A和Api_B,在創(chuàng)建一個網(wǎng)關(guān)項目Api_Gateway,網(wǎng)關(guān)項目可以選擇空的模板。

          現(xiàn)在分別在Api_A和Api_B中寫幾個api,將默認(rèn)的WeatherForecastController中返回模型WeatherForecast添加一個字段Source,用于區(qū)分是哪個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?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?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中添加兩個控制器:ApiAController、ApiBController,然后加上幾個簡單的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項目分別就有了6個接口。

          接著打包docker鏡像,放在docker中運行這兩個api項目。這一步可以用任何你熟悉的方式,run起來即可。

          docker?build?-t?api_a:dev?-f?./Api_A/Dockerfile?.
          docker?build?-t?api_b:dev?-f?./Api_B/Dockerfile?.

          build成功后,指定兩個端口運行api項目。

          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端口,通過 http://localhost:5050/swagger打開可以看到swagger文檔界面,Api_B指定了5051端口,通過 http://localhost:5051/swagger打開可以看到swagger文檔界面,這樣就大功告成了,接下來才是重點將兩個api項目配置到Api_Gateway網(wǎng)關(guān)項目中。

          配置網(wǎng)關(guān)

          在網(wǎng)關(guān)項目Api_Gateway中都添加Ocelot組件包。

          Install-Package Ocelot

          Ocelot中最關(guān)鍵的就是配置路由信息,新建一個ocelot.json配置文件,將我們的兩個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)于配置文件中的各項具體含義,可以參考官方文檔中的介紹。主要就是將DownstreamPathTemplate模板內(nèi)容轉(zhuǎn)換為UpstreamPathTemplate模板內(nèi)容進(jìn)行接口的訪問,同時可以指定HTTP請求的方式等等。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.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();
          ????????}
          ????}
          }

          完成以上操作后,我們試著去調(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"

          可以看到,兩個項目中的接口全部可以通過網(wǎng)關(guān)項目暴露的地址進(jìn)行中轉(zhuǎn),是不是很方便?

          本篇只是簡單的應(yīng)用,對于Ocelot的功能遠(yuǎn)不止于此,它非常強大,還可以實現(xiàn)請求聚合、服務(wù)發(fā)現(xiàn)、認(rèn)證、鑒權(quán)、限流熔斷、并內(nèi)置了負(fù)載均衡器,而且這些功能都是只需要簡單的配置即可完成。就不一一描述了,如有實際開發(fā)需求和問題,可以查看官方文檔和示例。







          回復(fù)?【關(guān)閉】學(xué)關(guān)
          回復(fù)?【實戰(zhàn)】獲取20套實戰(zhàn)源碼
          回復(fù)?【被刪】學(xué)
          回復(fù)?【訪客】學(xué)
          回復(fù)?【小程序】學(xué)獲取15套【入門+實戰(zhàn)+賺錢】小程序源碼
          回復(fù)?【python】學(xué)微獲取全套0基礎(chǔ)Python知識手冊
          回復(fù)?【2019】獲取2019 .NET 開發(fā)者峰會資料PPT
          回復(fù)?【加群】加入dotnet微信交流群

          90后中國程序員“黑吃黑”博彩網(wǎng)站,半年獲利256萬,判刑11年半


          PanDownload復(fù)活了,60MB/s,目前已開源!



          瀏覽 36
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99国精产品自偷自偷综合 | 国产福利AV | 国产视频麻豆 | 五月天成人在线观看视频 | 伊人久久97 |