(精华)2020年8月22日 微服务 Consul服务中心的使用(.net core版)

289 阅读3分钟

一、安装Consul

1.官网下载对应版本,并解压出来

官网网址:www.consul.io/

2.打开cmd,cd到解压的目录,运行如下其中一条命令

本次演示都在同一台计算机上,所以本文选择命令一;这两条命令请在开发环境使用,生产环境不要使用。

命令一:“consul.exe agent -dev”服务中心的ip地址,将会使用127.0.0.1

命令二:“consul.exe agent -dev -client x.x.x.x”指定服务中心的ip地址

3.命令运行成功后,打开“http://127.0.0.1:8500/”,出现如下画面

在这里插入图片描述

二、创建服务

1.服务端项目大体结构:

在这里插入图片描述

2.新建.NET Core类库项目,命名为“ClassLibrary”,然后NuGet搜索并安装

“Consul”、“Microsoft.Extensions.Configuration”、“Microsoft.Extensions.Configuration.Json”

Common.cs代码:

using Consul;
using Microsoft.Extensions.Configuration;
using System;

namespace ClassLibrary
{
    public class Common
    {
        public static IConfiguration Configuration { get; }
        static Common()
        {
            Configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", false, true).Build();
        }

        /// <summary>
        /// 需要注册的服务地址
        /// </summary>
        public static string ConsulServiceIP
        {
            get
            {
                return Configuration["Consul:ServiceIP"];
            }
        }

        /// <summary>
        /// 需要注册的服务端口
        /// </summary>
        public static int ConsulServicePort
        {
            get
            {
                string str = Configuration["Consul:ServicePort"];
                return int.Parse(str);
            }
        }

        /// <summary>
        /// 服务注册
        /// </summary>
        public static void ConsulRegister()
        {
            ConsulClient client = new ConsulClient(
                (ConsulClientConfiguration c) =>
                {
                    c.Address = new Uri(Configuration["Consul:Address"]); //Consul服务中心地址
                    c.Datacenter = Configuration["Consul:DataCenter"]; //指定数据中心,如果未提供,则默认为代理的数据中心。
                }
            );
            string checkUrl = Configuration["Consul:CheckUrl"];
            client.Agent.ServiceRegister(new AgentServiceRegistration()
            {
                ID = Guid.NewGuid().ToString(), //服务编号,不可重复
                Name = Configuration["Consul:ServiceName"], //服务名称
                Port = ConsulServicePort, //本程序的端口号
                Address = ConsulServiceIP, //本程序的IP地址
                Check = new AgentServiceCheck()
                {
                    DeregisterCriticalServiceAfter = TimeSpan.FromMilliseconds(1), //服务停止后多久注销
                    Interval = TimeSpan.FromSeconds(5), //服务健康检查间隔
                    Timeout = TimeSpan.FromSeconds(5), //检查超时的时间
                    HTTP = $"http://{ConsulServiceIP}:{ConsulServicePort}{checkUrl}" //检查的地址
                }
            });
        }

    }
}

3.新建.NET Core的webapi项目,命名为“ServiceStudent”,把“为HTTPS配置”的勾选去掉

Controller代码:

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;

namespace ServiceStudent.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class DefaultController : ControllerBase
    {
        static List<Student> list = new List<Student>() {
            new Student(){ ID = "001", StudentName = "学生1", StudentAge = 16 },
            new Student(){ ID = "002", StudentName = "学生2", StudentAge = 18 },
            new Student(){ ID = "003", StudentName = "学生3", StudentAge = 17 }
        };

        /// <summary>
        /// 健康检查接口
        /// </summary>
        [HttpGet]
        public string Check()
        {
            return "1";
        }

        [HttpGet]
        public List<Student> GetList()
        {
            Console.WriteLine(DateTime.Now.ToString());
            return list;
        }

        [HttpGet]
        public Student GetModel(string id)
        {
            Console.WriteLine(DateTime.Now.ToString());
            return list.Find(t => t.ID == id);
        }
    }
}

其中有一段健康检查的接口,作用是让服务中心知道服务没有挂掉还能访问,不需要什么业务,所以怎么简单怎么来:
在这里插入图片描述
Model代码:

public class Student
{
    public string ID { get; set; }
    public string StudentName { get; set; }
    public int StudentAge { get; set; }
}

appsettings.json的配置,加入"Consul",注意ServiceIP改为自己电脑的IP(这个不要配置为127.0.0.1,后面访问会不正常)

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "Consul": {
    "Address": "http://127.0.0.1:8500",
    "CheckUrl": "/api/Default/Check",
    "DataCenter": "dc1",
    "ServiceIP": "192.168.2.119",
    "ServicePort": 551,
    "ServiceName": "Student"
  }
}

Program.cs的CreateHostBuilder方法改为:

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureWebHostDefaults(webBuilder =>
        {
            string ip = Common.ConsulServiceIP;
            int port = Common.ConsulServicePort;
            webBuilder.UseStartup<Startup>().UseUrls($"http://{ip}:{port}");
        });

在Startup.cs的Configure方法中加入“ClassLibrary.Common.ConsulRegister();”

在这里插入图片描述

这样一个“Student”服务就创建好了,“Teacher”服务也是如法炮制,但是需要改appsettings.json的服务名和端口号。

三、启动服务

通过命令行来启动,打开cmd,cd到Debug目录,各自运行“dotnet ServiceStudent.dll”和“dotnet ServiceTeacher.dll”。

请检查端口有没有被占用或超出范围,如果失败了,在配置文件中换成其它端口试试。
在这里插入图片描述
在这里插入图片描述
服务运行成功后,打开“http://127.0.0.1:8500/”,如下画面注册成功
在这里插入图片描述
一个服务可能会部署到多个服务器上,用“Teacher”来模拟下多台机器运行。

前面运行好的服务不要关闭,打开Teacher的Debug目录下的配置文件,

修改它的端口号,服务名不用改,再新开一个cmd,运行“dotnet ServiceTeacher.dll”
在这里插入图片描述
那么服务中心就会有变化
在这里插入图片描述

四、使用服务

1.客户端项目大体结构:
在这里插入图片描述
2.新建.net core类库项目,命名为“ClassLibrary”,然后NuGet搜索并安装

“Consul”、“Microsoft.Extensions.Configuration”

Common.cs代码:

using Consul;
using Microsoft.Extensions.Configuration;
using System;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;

namespace ClassLibrary
{
    public class Common
    {
        public static IConfiguration Configuration { get; }
        static Common()
        {
            Configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", false, true).Build();
        }

        public static string ConsulAddress
        {
            get { return Configuration["ConsulAddress"]; }
        }

        /// <summary>
        /// 获取服务
        /// </summary>
        public static string GetService(string serviceName)
        {
            ConsulClient client = new ConsulClient(c => c.Address = new Uri(ConsulAddress));

            var response = client.Agent.Services().Result.Response;

            //服务名称区分大小写,若要不区分:Equals(serviceName, StringComparison.OrdinalIgnoreCase)
            var services = response.Where(s => s.Value.Service.Equals(serviceName)).Select(s => s.Value);

            //进行取模,随机取得一个服务器,或者使用其它负载均衡策略
            var service = services.ElementAt(Environment.TickCount % services.Count());

            return service.Address + ":" + service.Port;
        }

        /// <summary>
        /// 获取服务(异步方法)
        /// </summary>
        public async Task<string> GetService2(string serviceName)
        {
            ConsulClient client = new ConsulClient(c => c.Address = new Uri(ConsulAddress));

            var response = (await client.Agent.Services()).Response;

            //服务名称区分大小写,若要不区分:Equals(serviceName, StringComparison.OrdinalIgnoreCase)
            var services = response.Where(s => s.Value.Service.Equals(serviceName)).Select(s => s.Value);

            //进行取模,随机取得一个服务器,或者使用其它负载均衡策略
            var service = services.ElementAt(Environment.TickCount % services.Count());

            return service.Address + ":" + service.Port;
        }

        public static string HttpGetString(string url)
        {
            HttpClient httpClient = new HttpClient();
            string result = httpClient.GetAsync(url)
            .Result.Content.ReadAsStringAsync().Result;
            httpClient.Dispose();
            return result;
        }

        public static T HttpGetObject<T>(string url)
        {
            string result = HttpGetString(url);
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(result);
        }

    }
}

3.新建.NET Core的webapi项目,命名为“ClientSite”,把“为HTTPS配置”的勾选去掉

StudentController代码:

using ClassLibrary;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace ClientSite.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class StudentController : ControllerBase
    {
        [HttpGet]
        public object GetList()
        {
            string ip = Common.GetService("Student");
            List<Student> list = Common.HttpGetObject<List<Student>>($"http://{ip}/api/Default/GetList");
            return new
            {
                address = ip,
                data = list
            };
        }

        [HttpGet]
        public object GetModel(string id)
        {
            string ip = Common.GetService("Student");
            Student model = Common.HttpGetObject<Student>($"http://{ip}/api/Default/GetModel?id={id}");
            return new
            {
                address = ip,
                data = model
            };
        }
    }
}

TeacherController代码:

using ClassLibrary;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;

namespace ClientSite.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    public class TeacherController : ControllerBase
    {
        [HttpGet]
        public object GetList()
        {
            string ip = Common.GetService("Teacher");
            List<Teacher> list = Common.HttpGetObject<List<Teacher>>($"http://{ip}/api/Default/GetList");
            return new
            {
                address = ip,
                data = list
            };
        }

        [HttpGet]
        public object GetModel(string id)
        {
            string ip = Common.GetService("Teacher");
            Teacher model = Common.HttpGetObject<Teacher>($"http://{ip}/api/Default/GetModel?id={id}");
            return new
            {
                address = ip,
                data = model
            };
        }
    }
}

appsettings.json加入:

"ConsulAddress": "http://127.0.0.1:8500"

在这里插入图片描述
4.用VS启动站点,然后用postman访问

“http://ip:port/api/Student/GetList”

“http://ip:port/api/Student/GetModel?id=002”
在这里插入图片描述
在这里插入图片描述
多次访问“http://ip:port/api/Teacher/GetList”,则address会随机切换,注意看返回的端口号
在这里插入图片描述
代码:files.cnblogs.com/files/shous…