zoukankan      html  css  js  c++  java
  • 使用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.预告

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

  • 相关阅读:
    解决Warning: Cannot modify header information headers already sent b...
    C#获取文件路径的几种方法
    C#反射技术之一读取和设置类的属性
    WPF中,在WebBrowser中操作源代码
    WPF 的 TabControl 绑定不同的窗口集合
    C#_在VS2010下进行单元测试
    Mvvm Light Toolkit for wpf/silverlight系列之Command和Events
    VS2005和VS2008快捷键大全(转)
    nchar,char,varchar 与nvarchar区别
    处理问题:windows server 2016由于没有远程桌面授权服务器可以提供许可证,远程会话被中断。请跟服务器管理员联系...
  • 原文地址:https://www.cnblogs.com/hanfan/p/10299122.html
Copyright © 2011-2022 走看看