欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-04-28 13:55:46
1.下载打开Consul 笔者是windows下面开发的(也可以使用Docker)。 官网下载windows的Consul https://www.consul.io/ 使用cmd窗口打开,输入 访问默认127.0.0.1:8500就可以看到界面化的Consul 2.在服务端注册 接着上一篇 app ......
1.下载打开consul

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

使用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.预告

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