.Net Core微服務入門全紀錄(四)——Ocelot-API網關(上)

前言

上一篇【.Net Core微服務入門全紀錄(三)——Consul-服務註冊與發現(下)】已經使用Consul完成了服務的註冊與發現,實際中光有服務註冊與發現每每是不夠的,咱們須要一個統一的入口來鏈接客戶端與服務。html

Ocelot

官網:https://ocelot.readthedocs.io/
Ocelot正是爲.Net微服務體系提供一個統一的入口點,稱爲:Gateway(網關)。git

  • 上手Ocelot:

首先建立一個空的asp.net core web項目。

注意ocelot.json是咱們添加的Ocelot的配置文件,記得設置生成時複製到輸出目錄。ocelot.json的文件名不是固定的,能夠本身定義。github

NuGet安裝一下Ocelot:
web

只需簡單的修改幾處默認代碼:
Program.cs:docker

public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    config.AddJsonFile("ocelot.json");
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }

Startup.cs:json

public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            //添加ocelot服務
            services.AddOcelot();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            //設置Ocelot中間件
            app.UseOcelot().Wait();
        }
    }

ocelot.json:api

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/products",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 9050
        },
        {
          "Host": "localhost",
          "Port": 9051
        },
        {
          "Host": "localhost",
          "Port": 9052
        }
      ],
      "UpstreamPathTemplate": "/products",
      "UpstreamHttpMethod": [
        "Get"
      ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin" //負載均衡,輪詢機制 LeastConnection/RoundRobin/NoLoadBalancer/CookieStickySessions
      }
    },
    {
      "DownstreamPathTemplate": "/orders",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 9060
        },
        {
          "Host": "localhost",
          "Port": 9061
        },
        {
          "Host": "localhost",
          "Port": 9062
        }
      ],
      "UpstreamPathTemplate": "/orders",
      "UpstreamHttpMethod": [
        "Get"
      ],
      "LoadBalancerOptions": {
        "Type": "RoundRobin" //負載均衡,輪詢機制 LeastConnection/RoundRobin/NoLoadBalancer/CookieStickySessions
      }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "http://localhost:9070"
  }
}

咱們先暫時忽略Consul,將服務實例的地址都寫在配置文件中。要知道Consul、Ocelot等組件都是能夠獨立存在的。
配置文件中的Routes節點用來配置路由,Downstream表明下游,也就是服務實例,Upstream表明上游,也就是客戶端。咱們的路徑比較簡單,只有/products、/orders,路徑中若是有不固定參數則使用{}匹配。咱們這個配置的意思呢就是客戶端訪問網關的/orders、/products,網關會轉發給服務實例的/orders、/products,注意這個上游的路徑不必定要和下游一致,好比上游路徑能夠配置成/api/orders,/xxx均可以。
LoadBalancerOptions節點用來配置負載均衡,Ocelot內置了 LeastConnection、RoundRobin、NoLoadBalancer、CookieStickySessions 4種負載均衡策略。
BaseUrl節點就是配置咱們ocelot網關將要運行的地址。瀏覽器

  • 運行gateway:

目前不考慮網關集羣,就不放在docker裏了。直接控制檯執行:`dotnet Ocelot.APIGateway.dll --urls="http://*:9070"
app

用瀏覽器測試一下:


測試正常,咱們經過網關能夠正常的訪問到服務實例。負載均衡

  • 接下來繼續改造客戶端代碼:


由於改動太多就直接新建一個GatewayServiceHelper來作。
GatewayServiceHelper:

/// <summary>
    /// 經過gateway調用服務
    /// </summary>
    public class GatewayServiceHelper : IServiceHelper
    {
        public async Task<string> GetOrder()
        {
            var Client = new RestClient("http://localhost:9070");
            var request = new RestRequest("/orders", Method.GET);

            var response = await Client.ExecuteAsync(request);
            return response.Content;
        }

        public async Task<string> GetProduct()
        {
            var Client = new RestClient("http://localhost:9070");
            var request = new RestRequest("/products", Method.GET);

            var response = await Client.ExecuteAsync(request);
            return response.Content;
        }

        public void GetServices()
        {
            throw new NotImplementedException();
        }
    }

而後在Startup中修改一下注入的類型,別的就不用改了,這就是依賴注入的好處之一。。。
Startup.ConfigureServices():

//注入IServiceHelper
//services.AddSingleton<IServiceHelper, ServiceHelper>();
            
//注入IServiceHelper
services.AddSingleton<IServiceHelper, GatewayServiceHelper>();

Startup.Configure():

//程序啓動時 獲取服務列表
//serviceHelper.GetServices();

運行客戶端測試:

好了,如今客戶端對服務的調用都經過網關進行中轉,客戶端不再用去關心那一堆服務實例的地址,只須要知道網關地址就能夠了。另外,服務端也避免了服務地址直接暴露給客戶端。這樣作對客戶端,服務都很是友好。

至於咱們的api網關呢,又要說到服務發現的問題了。目前咱們的服務地址是寫在ocelot.json配置文件裏的,固然這種作法在服務實例不常常變化的狀況下是沒有問題的,一旦服務變化,須要人爲的修改配置文件,這又顯得不太合理了。

固然,強大的Ocelot爲咱們提供了服務發現的方案。

代碼放在:https://github.com/xiajingren/NetCoreMicroserviceDemo

未完待續...

相關文章
相關標籤/搜索