前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微服务之Consul服务自动注册

微服务之Consul服务自动注册

原创
作者头像
用户2295386
修改2020-06-11 10:08:09
2.2K0
修改2020-06-11 10:08:09
举报
文章被收录于专栏:ASP.NET Core微服务

安装Consul

我用的是Win 10的系统,但是安装了Docker Desktop,

然后用powershell进行docker的相关操作。

  • pull一个consul镜像到本地
代码语言:txt
复制
PS C:\Users\Zhanwei> docker pull consul

Using default tag: latest

latest: Pulling from library/consul

31603596830f: Pull complete

e424a2a1e4f7: Pull complete

2472846eab82: Pull complete

24473b564e4a: Pull complete

b3caf5938c68: Pull complete

b6f50757bb0c: Pull complete

Digest: sha256:1cb6f7247472638c470c1bcf059a1f74a4d54c6b49c57c80651feb08cc0a80cf

Status: Downloaded newer image for consul:latest

docker.io/library/consul:latest

PS C:\Users\Zhanwei>
  • 运行一个Consul
代码语言:txt
复制
PS C:\Users\Zhanwei> docker run -d -p 8500:8500 -v /data/consul:/consul/data -e CONSUL\_BIND\_INTERFACE='eth0' --name=consul\_server\_1 consul:latest agent -server -bootstrap -ui -node=node-1 -client='0.0.0.0' -datacenter=hangzhou

9d5e1c54ee6e44efc100e5a6fdf4e4f22ad2a177e0f0d937e54bb9b245e657cd

**参数说明:**

  • server: 以server身份启动。默认是client
  • bootstrap-expect:集群要求的最少server数量,当低于这个数量,集群即失效。
  • data-dir:data存放的目录,更多信息请参阅consul数据同步机制
  • node:节点id,集群中的每个node必须有一个唯一的名称。默认情况下,Consul使用机器的hostname
  • bind:监听的ip地址。默认绑定0.0.0.0,可以不指定。表示Consul监听的地址,而且它必须能够被集群中的其他节点访问。Consul默认会监听第一个private IP,但最好还是提供一个。生产设备上的服务器通常有好几个网卡,所以指定一个不会出错
  • client: 客户端的ip地址,0.0.0.0是指谁都可以访问(不加这个,下面的ui :8500无法访问)
  • ui: 可以访问UI界面
  • -config-dir指定配置文件夹,Consul会加载其中的所有文件
  • -datacenter 指定数据中心名称,默认是dc1

打开浏览器,如下所示,IP换成自己的IP

p1.png
p1.png

这样单机版的Consul就启动完成了,接下来我们新建个API服务。

新建WEB API服务项目

  • 新建一个名为CustomMiddleware.api01的API项目。
  • 安装Consul依赖包。
代码语言:txt
复制
PM>Install-Package Consul -Version 0.7.2.6
  • 自动注册服务到Consul,退出时取消注册。

如果是主动退出服务,会执行取消注册的方法,好处是比心跳响应更快,但是心跳也是必不可少的,因为在微服务中,各种网络原因都有可能导致服务异常中断。

我这里是封装了一个方法来注册,代码如下所示:

代码语言:txt
复制
public static void RegisterConsul(this IApplicationBuilder app,IApplicationLifetime lifetime, ServiceEntity serviceEntity)

{

    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 = $"http://{serviceEntity.IP}:{serviceEntity.Port}/api/health",//健康检查地址

        Timeout = TimeSpan.FromSeconds(5)

    };



    // Register service with consul

    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();

            

    lifetime.ApplicationStopping.Register(() =>

    {

        consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服务停止时取消注册

    });

}

ID:正常环境中最好不要用guid,因为每次启动id都不一样,正常来讲没啥问题,但是快速启动时就会有个坑了。建议用,这样也是唯一的,并且不会重复。

代码语言:txt
复制
ID=$"{serviceEntity.ServiceName}\_{serviceEntity.IP}\_{serviceEntity.Port}"
  • 修改Program

我想在用dotnet运行项目时,能够传入url,ip和port,所以在这里加了命令行参数。

代码语言:txt
复制
public static IHostBuilder CreateHostBuilder(string[] args) =>

    Host.CreateDefaultBuilder(args)

    .ConfigureAppConfiguration(build =>

    {

        build.AddCommandLine(args);//启动时可读取命令行参数

    })

    .ConfigureWebHostDefaults(webBuilder =>

    {

        webBuilder.UseStartup<Startup>();

    });
  • 修改Configure方法,在最后加上RegisterConsul()
代码语言:txt
复制
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, Microsoft.AspNetCore.Hosting.IApplicationLifetime lifetime)

{

    if (env.IsDevelopment())

    {

        app.UseDeveloperExceptionPage();

    }



    app.UseRouting();

    app.UseAuthorization();



    app.UseEndpoints(endpoints =>

    {

        endpoints.MapControllers();

    });

    

    //获取环境变量

    var ip = Configuration.GetValue(typeof(String), "IP");

    var port = Configuration.GetValue(typeof(String), "Port");

    ServiceEntity serviceEntity = new ServiceEntity

    {

        IP = ip.ToString(),

        Port = Convert.ToInt32(port),

        ServiceName = Configuration["Service:Name"],

        ConsulIP = Configuration["Consul:IP"],

        ConsulPort = Convert.ToInt32(Configuration["Consul:Port"])

    };



    app.RegisterConsul(lifetime, serviceEntity);

}
  • 新建一个控制器,添加一个接口,用来测试。
代码语言:txt
复制
[Route("api/[controller]")]

[ApiController]

public class DefaultController : ControllerBase

{

    // GET: api/Default

    [HttpGet]

    public ResultInfo Get()

    {

        ResultInfo result = new ResultInfo();

        result.Code = 200;

        result.CreateTime = DateTime.Now;

        result.Message = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}{HttpContext.Request.Path}";



        result.Data = new {

                name="zhanwei",

                server="Api01"

        };

        return result;

    }

}
  • 加上Health健康检查
代码语言:txt
复制
    [Route("api/[controller]")]

    [ApiController]

    public class HealthController : ControllerBase

    {

        [HttpGet]

        public IEnumerable<string> Get()

        {

            return new string[] { "result", "ok" };

        }

    }
  • ServiceEntity实体类
代码语言:txt
复制
    public class ServiceEntity

    {

        public string IP { get; set; }

        public int Port { get; set; }

        public string ServiceName { get; set; }

        public string ConsulIP { get; set; }

        public int ConsulPort { get; set; }

    }
  • 修改配置文件,增加如下内容
代码语言:txt
复制
  "Service": {

    "Name": "Api01"//注册到Consul中显示的服务名称

  },

  "Consul": {

    "IP": "192.168.10.134",//改成实际Consul地址

    "Port": "8500"//Consul的端口

  }

测试

  • 启动两个实例,只不过换一下端口号,我们看一下效果,用下面这个命令传入
代码语言:txt
复制
dotnet CustomMiddleware.api01.dll --urls="http://\*:5001/" --ip="192.168.10.134" --port="5001"
  • 如下图所示,我们起来了两个实例。
p2.png
p2.png
  • 打开Consul网页客户端,我们看到Api01有两个实例
p3.png
p3.png
  • 验证下两个服务的接口是否正常的
p6.png
p6.png
p7.png
p7.png

我们可以看到分别访问两个接口都是能正常返回的,这两个接口后面介绍网关负载均衡的时候还会用到,可以从返回的信息里区别是从哪个实例返回的。

再新建一个API服务

重复的过程就不再赘述了,我只是修改了下接口的路径,还有服务名称。

  • 启动一个实例
p4.png
p4.png
  • 打开网页端,可以看到Api02也已经注册进去了。
p5.png
p5.png

下期预告

现在就完成了服务的自动注册功能,其实光注册进去是没什么作用的,这只是为后续做准备而已,后面我会利用Ocelot组件做一个简单的网关,网关又是什么?

  • 服务自动发现、路由转发、负载均衡、限流、熔断等功能的讲解。
  • Consul单机版挂掉了不就完蛋了吗,所以后面还会介绍集群的搭建。

总之后面很精彩,这才刚起步而已。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 安装Consul
  • 新建WEB API服务项目
  • 测试
  • 再新建一个API服务
  • 下期预告
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档