使用Consul 實現 MagicOnion(GRpc) 服務註冊和發現

1.下載打開Consul

筆者是windows下面開發的(也能夠使用Docker)。
官網下載windows的Consuljson

https://www.consul.io/windows

使用cmd窗口打開,輸入consul agent -dev
訪問默認127.0.0.1:8500就能夠看到界面化的Consulapi

2.在服務端註冊

接着上一篇app

using Consul;
using Grpc.Core;
using GRPCServer.Entity;
using MagicOnion.Server;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;

namespace GRPCServer
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            this.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().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            MagicOnionServiceDefinition service = MagicOnionEngine.BuildServerServiceDefinition(new MagicOnionOptions(true)
            {
                MagicOnionLogger = new MagicOnionLogToGrpcLogger()
            });
            Server server = new Server
            {
                Services = { service },
                Ports = { new ServerPort(this.Configuration["Service:LocalIPAddress"], Convert.ToInt32(this.Configuration["Service:Port"]), ServerCredentials.Insecure) }
            };
            server.Start();

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            } 
            app.UseMvc(); 
             
            ServiceEntity serviceEntity = new ServiceEntity
            {
                IP = this.Configuration["Service:LocalIPAddress"],
                Port = Convert.ToInt32(this.Configuration["Service:Port"]),
                ServiceName = this.Configuration["Service:Name"],
                ConsulIP = this.Configuration["Consul:IP"],
                ConsulPort = Convert.ToInt32(this.Configuration["Consul:Port"])
            };
            var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{serviceEntity.ConsulIP}:{serviceEntity.ConsulPort}"));//請求註冊的 Consul 地址
            var httpCheck = new AgentServiceCheck()
            {
                DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服務啓動多久後註冊
                Interval = TimeSpan.FromSeconds(10),//健康檢查時間間隔,或者稱爲心跳間隔
                HTTP = this.Configuration["Service:Examination"],//健康檢查地址
                Timeout = TimeSpan.FromSeconds(5)
            };
            var registration = new AgentServiceRegistration()
            {
                Checks = new[] { httpCheck },
                ID = Guid.NewGuid().ToString(),
                Name = serviceEntity.ServiceName,
                Address = serviceEntity.IP,
                Port = serviceEntity.Port,
                Tags = new[] { $"urlprefix-/{serviceEntity.ServiceName}" }//添加 urlprefix-/servicename 格式的 tag 標籤,以便 Fabio 識別
            }; 
            consulClient.Agent.ServiceRegister(registration).Wait();//服務啓動時註冊,內部實現其實就是使用 Consul API 進行註冊(HttpClient發起)
            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服務中止時取消註冊
            }); 
        }
    }
}

appsettings.jsonasync

{
  "Service": {
    "Name": "Test3",
    "Port": "8083",
    "LocalIPAddress": "192.168.1.8",
    "Examination": "http://192.168.1.8:5000/api/Values"
  },
  "Consul": {
    "IP": "127.0.0.1",
    "Port": "8500"
  }
}
3.客戶端調用
using Consul;
using Grpc.Core;
using MagicOnion.Client;
using ServerDefinition;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;


var aaa= AvaliableServices("Test3","").Result;


public static async Task<ServiceEntry[]> AvaliableServices(string name, string tags)
        {
            var services = new List<ServiceEntry>();
            using (var client = new ConsulClient())
            {
                foreach (var tag in tags.Split(','))
                {
                    var result = await client.Health.Service(name, !string.IsNullOrEmpty(tag) ? tag : null, true).ConfigureAwait(false);
                    foreach (var item in result.Response)
                    {
                        if (!services.Any(service => service.Node.Address == item.Node.Address
                            && service.Service.Port == item.Service.Port))
                        {
                            services.Add(item);
                        }
                    } 
                }
                //交集處理,僅取出徹底匹配服務
                foreach (var tag in tags.Split(','))
                {
                    if (string.IsNullOrEmpty(tag))
                    {
                        continue;
                    }
                    var alsorans = services.Where(service => !service.Service.Tags.Contains(tag)).ToList();
                    foreach (var alsoran in alsorans)
                    {
                        services.Remove(alsoran);
                    }
                }
            }
            return services.ToArray();
        }
4.思考

這個時候我就能經過'Test3'來得到Test3的服務和接口。微服務

可是我是使用的MagicOnion,仍是沒辦法拿到我定義的方法SumAsyncui

怎麼辦?this

1.引用ITest (讓微服務之間有引用,不太好)url

2.使用網關spa

5.預告

下一篇我會想法辦法使他們能相互通信(其實我還不知道怎麼搞)

相關文章
相關標籤/搜索