dotnet core微服務框架Jimu ~ 基礎閘道器

Flamesky發表於2024-12-03

閘道器提供外部訪問內部微服務的統一入口,基於分散式和服務治理等功能特點,外部不能繞過閘道器呼叫內部微服務(框架本身提供外部可以直接訪問內部微服務的功能,這裡不作詳細說明),外部透過 http 協議請求閘道器暴露的介面,閘道器再用基於 TCP/IP 協議的 RPC 方式呼叫內部被發現的微服務。

1 建立閘道器

建立一個基於 .Net Core 6.0 的 Asp.Net Core Web (專案模版選 WebApi)的專案,命名為 ApiGateway

1.1 新增 Jimu.Client 引用

閘道器相對於微服務而言屬於客戶端,所以引用 Jimu.Client,因為需要支援 Consul, 所以還要因為 Jimu 對 consul 的擴充套件庫 Jimu.Common.Discovery.ConsulIntegration

Install-Package  Jimu.Client
Install-Package  Jimu.Common.Discovery.ConsulIntegration

1.2 然後在 Startup 裡新增 Jimu 的啟動程式碼

using System.Linq;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using Autofac;
using Jimu;
using Jimu.Client;
using Jimu.Client.ApiGateway;

namespace ApiGateway
{
    public class Startup
    {
        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.AddCors(); // 支援跨域
            services.UseJimu();  // 支援 Jimu
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {

            app.UseStaticFiles();
            app.UseAuthentication();
            app.UseStatusCodePages();

            // jimu client, 啟動 jimu 
            var host = new ServiceHostClientBuilder(new ContainerBuilder())
                .UseLog4netLogger(new LogOptions
                {
                    EnableConsoleLog = true,  // 啟用控制檯日誌
                    EnableFileLog = true, // 啟用檔案日誌
                    FileLogLevel = LogLevel.Info | LogLevel.Error, // 檔案日誌只記錄 Info 和 Error
                })
                .UseConsulForDiscovery("127.0.0.1", 8500, "JimuService") // 配置 consul 
                .UseDotNettyForTransfer() // 使用 dotnetty 做 RPC 的通訊庫
                .UseHttpForTransfer() // 同時支援使用  http 作為 RPC 的通訊庫
                .UsePollingAddressSelector() // 使用輪詢演算法實現負載均衡
                .UseServerHealthCheck(1) // 服務健康監控,時間間隔為 1 分鐘
                .SetRemoteCallerRetryTimes(3) // 呼叫微服務失敗重試次數,設為 3次
                .SetDiscoveryAutoUpdateJobInterval(1) // 服務發現,時間間隔 1 分鐘
                .UseToken(() => { var headers = JimuHttpContext.Current.Request.Headers["Authorization"]; return headers.Any() ? headers[0] : null; }) // 獲取請求所攜帶的 token
                .Build();
            app.UseJimu(host); // 使用 jimu
            host.Run(); // 啟動 jimu
        }
    }
}

最基本的閘道器完成了,已經支援接收請求。 下面要加入一些視覺化的服務治理,如微伺服器列表,伺服器健康狀態,服務列表

1.3 服務治理

服務治理還未完善,只簡單做了伺服器列表和健康狀態,以及開放的服務列表。

建立 2 個控制器:

1.3.1 Server 展示伺服器列表

using Autofac;
using Jimu;
using Jimu.Client;
using Jimu.Client.ApiGateway;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ApiGateway.Controllers
{
    public class ServerController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
        //[HttpGet(Name ="addresses")]
        // 獲取伺服器列表
        public async Task<List<JimuAddress>> GetAddresses()
        {
            var serviceDiscovery = JimuClient.Host.Container.Resolve<IClientServiceDiscovery>();
            var addresses = await serviceDiscovery.GetAddressAsync();
            return addresses;

        }

    }
}

注意:控制器和方法上面都不需新增任何屬性

1.3.2 Services 展示服務列表

using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Autofac;
using Jimu;
using Jimu.Client;
using Jimu.Client.ApiGateway;
using Microsoft.AspNetCore.Mvc;

namespace ApiGateway.Controllers
{
    //[Produces("application/json")]
    public class ServicesController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
        //[HttpGet(Name ="services")]
        // 獲取服務列表
        public async Task<List<JimuServiceDesc>> GetServices(string server)
        {
            var serviceDiscovery = JimuClient.Host.Container.Resolve<IClientServiceDiscovery>();
            var routes = await serviceDiscovery.GetRoutesAsync();
            if (routes != null && routes.Any() && !string.IsNullOrEmpty(server))
            {
                return (from route in routes
                        where route.Address.Any(x => x.Code == server)
                        select route.ServiceDescriptor).ToList();
            }
            return (from route in routes select route.ServiceDescriptor).ToList();
        }
    }
}

相關文章