微服务学习笔记(2)——使用Consul 实现 MagicOnion(GRpc) 服务注册和发现

1.下载打开Consul

笔者是windows下面开发的(也可以使用Docker)。
官网下载windows的Consul

https://www.consul.io/

使用cmd窗口打开,输入consul agent -dev
访问默认127.0.0.1:8500就可以看到界面化的Consul

2.在服务端注册

接着上一篇

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.json

{
  "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,还是没办法拿到我定义的方法SumAsync

怎么办?

1.引用ITest (让微服务之间有引用,不太好)

2.使用网关

5.预告

下一篇我会想法办法使他们能相互通讯(其实我还不知道怎么搞)

猜你喜欢

转载自www.cnblogs.com/hanfan/p/10299122.html