.NET Core微服務一:Consul服務中心


.NET Core微服務一:Consul服務中心

.NET Core微服務二:Ocelot API網關

.NET Core微服務三:polly熔斷與降級

 

本文的項目代碼,在文章結尾處可以下載。

本文使用的環境:Windows10 64位 + VS 2019 + .NET Core 3.1

Consul有關介紹:https://www.jianshu.com/p/32dc52f28a14

Consul官方網址:https://www.consul.io/

 

 

一、安裝Consul

1.官網下載對應版本,並解壓出來

 

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代碼:

 1 using Consul;
 2 using Microsoft.Extensions.Configuration;
 3 using System;
 4 
 5 namespace ClassLibrary
 6 {
 7     public class Common
 8     {
 9         public static IConfiguration Configuration { get; }
10         static Common()
11         {
12             Configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", false, true).Build();
13         }
14 
15         /// <summary>
16         /// 需要注冊的服務地址
17         /// </summary>
18         public static string ConsulServiceIP
19         {
20             get
21             {
22                 return Configuration["Consul:ServiceIP"];
23             }
24         }
25 
26         /// <summary>
27         /// 需要注冊的服務端口
28         /// </summary>
29         public static int ConsulServicePort
30         {
31             get
32             {
33                 string str = Configuration["Consul:ServicePort"];
34                 return int.Parse(str);
35             }
36         }
37 
38         /// <summary>
39         /// 服務注冊
40         /// </summary>
41         public static void ConsulRegister()
42         {
43             ConsulClient client = new ConsulClient(
44                 (ConsulClientConfiguration c) =>
45                 {
46                     c.Address = new Uri(Configuration["Consul:Address"]); //Consul服務中心地址
47                     c.Datacenter = Configuration["Consul:DataCenter"]; //指定數據中心,如果未提供,則默認為代理的數據中心。
48                 }
49             );
50             string checkUrl = Configuration["Consul:CheckUrl"];
51             client.Agent.ServiceRegister(new AgentServiceRegistration()
52             {
53                 ID = Guid.NewGuid().ToString(), //服務編號,不可重復
54                 Name = Configuration["Consul:ServiceName"], //服務名稱
55                 Port = ConsulServicePort, //本程序的端口號
56                 Address = ConsulServiceIP, //本程序的IP地址
57                 Check = new AgentServiceCheck()
58                 {
59                     DeregisterCriticalServiceAfter = TimeSpan.FromMilliseconds(1), //服務停止后多久注銷
60                     Interval = TimeSpan.FromSeconds(5), //服務健康檢查間隔
61                     Timeout = TimeSpan.FromSeconds(5), //檢查超時的時間
62                     HTTP = $"http://{ConsulServiceIP}:{ConsulServicePort}{checkUrl}" //檢查的地址
63                 }
64             });
65         }
66 
67     }
68 }

 

3.新建.NET Core的webapi項目,命名為“ServiceStudent”,把“為HTTPS配置”的勾選去掉

Controller代碼:

 1 using Microsoft.AspNetCore.Mvc;  2 using System;  3 using System.Collections.Generic;  4 
 5 namespace ServiceStudent.Controllers  6 {  7     [Route("api/[controller]/[action]")]  8  [ApiController]  9     public class DefaultController : ControllerBase 10  { 11         static List<Student> list = new List<Student>() { 12             new Student(){ ID = "001", StudentName = "學生1", StudentAge = 16 }, 13             new Student(){ ID = "002", StudentName = "學生2", StudentAge = 18 }, 14             new Student(){ ID = "003", StudentName = "學生3", StudentAge = 17 } 15  }; 16 
17         /// <summary>
18         /// 健康檢查接口 19         /// </summary>
20  [HttpGet] 21         public string Check() 22  { 23             return "1"; 24  } 25 
26  [HttpGet] 27         public List<Student> GetList() 28  { 29  Console.WriteLine(DateTime.Now.ToString()); 30             return list; 31  } 32 
33  [HttpGet] 34         public Student GetModel(string id) 35  { 36  Console.WriteLine(DateTime.Now.ToString()); 37             return list.Find(t => t.ID == id); 38  } 39  } 40 }

 

其中有一段健康檢查的接口,作用是讓服務中心知道服務沒有掛掉還能訪問,不需要什么業務,所以怎么簡單怎么來:

 

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,后面訪問會不正常)

 1 {
 2   "Logging": {
 3     "LogLevel": {
 4       "Default": "Information",
 5       "Microsoft": "Warning",
 6       "Microsoft.Hosting.Lifetime": "Information"
 7     }
 8   },
 9   "AllowedHosts": "*",
10   "Consul": {
11     "Address": "http://127.0.0.1:8500",
12     "CheckUrl": "/api/Default/Check",
13     "DataCenter": "dc1",
14     "ServiceIP": "192.168.2.119",
15     "ServicePort": 551,
16     "ServiceName": "Student"
17   }
18 }

 

Program.cs的CreateHostBuilder方法改為:

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

 

在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/”,如下畫面注冊成功

 

如果出現一項打X,那就是失敗,這個服務會在1分鍾之后被踢出列表

 

一個服務可能會部署到多個服務器上,用“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代碼:

 1 using ClassLibrary;  2 using Microsoft.AspNetCore.Mvc;  3 using System.Collections.Generic;  4 
 5 namespace ClientSite.Controllers  6 {  7     [Route("api/[controller]/[action]")]  8  [ApiController]  9     public class StudentController : ControllerBase 10  { 11  [HttpGet] 12         public object GetList() 13  { 14             string ip = Common.GetService("Student"); 15             List<Student> list = Common.HttpGetObject<List<Student>>($"http://{ip}/api/Default/GetList"); 16             return new
17  { 18                 address = ip, 19                 data = list 20  }; 21  } 22 
23  [HttpGet] 24         public object GetModel(string id) 25  { 26             string ip = Common.GetService("Student"); 27             Student model = Common.HttpGetObject<Student>($"http://{ip}/api/Default/GetModel?id={id}"); 28             return new
29  { 30                 address = ip, 31                 data = model 32  }; 33  } 34  } 35 }

 

TeacherController代碼:

 1 using ClassLibrary;  2 using Microsoft.AspNetCore.Mvc;  3 using System.Collections.Generic;  4 
 5 namespace ClientSite.Controllers  6 {  7     [Route("api/[controller]/[action]")]  8  [ApiController]  9     public class TeacherController : ControllerBase 10  { 11  [HttpGet] 12         public object GetList() 13  { 14             string ip = Common.GetService("Teacher"); 15             List<Teacher> list = Common.HttpGetObject<List<Teacher>>($"http://{ip}/api/Default/GetList"); 16             return new
17  { 18                 address = ip, 19                 data = list 20  }; 21  } 22 
23  [HttpGet] 24         public object GetModel(string id) 25  { 26             string ip = Common.GetService("Teacher"); 27             Teacher model = Common.HttpGetObject<Teacher>($"http://{ip}/api/Default/GetModel?id={id}"); 28             return new
29  { 30                 address = ip, 31                 data = model 32  }; 33  } 34  } 35 }

 

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會隨機切換,注意看返回的端口號

 

 

 

 

代碼:https://files.cnblogs.com/files/shousiji/netcore_wfw.rar

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM