.NET Core微服務一:Consul服務中心 http://www.javashuo.com/article/p-pnigqhxw-e.htmlhtml
.NET Core微服務二:Ocelot API網關 待更新web
.NET Core微服務三:polly熔斷與降級 待更新json
本文的項目代碼,在文章結尾處能夠下載。api
本文使用的環境:Windows10 64位 + VS 2019 + .NET Core 3.1服務器
Consul有關介紹:https://www.jianshu.com/p/32dc52f28a14app
Consul官方網址:https://www.consul.io/負載均衡
1、安裝Consul異步
1.官網下載對應版本,並解壓出來async
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/」,出現以下畫面
2、建立服務
1.服務端項目大致結構:
2.新建.NET Core類庫項目,命名爲「ClassLibrary」,而後NuGet搜索並安裝
「Consul」、「Microsoft.Extensions.Configuration」
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["ConsulService:IP"]; 23 } 24 } 25
26 /// <summary>
27 /// 須要註冊的服務端口 28 /// </summary>
29 public static int ConsulServicePort 30 { 31 get
32 { 33 string str = Configuration["ConsulService:Port"]; 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["ConsulCenter:Address"]); //Consul服務中心地址
47 c.Datacenter = Configuration["ConsulCenter:DataCenter"]; //指定數據中心,若是未提供,則默認爲代理的數據中心。
48 } 49 ); 50 string checkUrl = Configuration["ConsulCenter:CheckUrl"]; 51 client.Agent.ServiceRegister(new AgentServiceRegistration() 52 { 53 ID = Guid.NewGuid().ToString(), //服務編號,不可重複
54 Name = Configuration["ConsulService:Name"], //服務名稱
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加入:
"ConsulCenter": {
"Address": "http://127.0.0.1:8500",
"CheckUrl": "/api/Default/Check",
"DataCenter": "dc1"
},
"ConsulService": {
"IP": "127.0.0.1",
"Port": 33331,
"Name": "Student"
}
Program.cs的CreateHostBuilder方法改成:
public static IHostBuilder CreateHostBuilder(string[] args) { string ip = Common.ConsulServiceIP; int port = Common.ConsulServicePort; return Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>().UseUrls($"http://{ip}:{port}"); }); }
在Startup.cs的Configure方法中加入「ClassLibrary.Common.ConsulRegister();」
這樣一個「Student」服務就建立好了,「Teacher」服務也是如法炮製,可是須要改appsettings.json的服務名和端口號,代碼就不貼了,請到文章結尾處下載。
3、啓動服務
不能在VS中啓動,由於咱們已經在Program.cs自定義了IP和PORT。
打開cmd,cd到Debug目錄,各自運行「dotnet ServiceStudent.dll」和「dotnet ServiceTeacher.dll」。
請檢查端口有沒有被佔用或超出範圍,若是失敗了,在配置文件中換成端口試試。
服務運行成功後,打開「http://127.0.0.1:8500/」,以下畫面註冊成功
若是出現一項打X,那就是失敗,這個服務會在1分鐘以後被踢出列表
一個服務可能會部署到多個服務器上,用「Teacher」來模擬下多臺機器運行。
前面運行好的服務不要關閉,打開Teacher的Debug目錄下的配置文件,修改它的端口號,服務名不用改,再新開一個cmd,運行「dotnet ServiceTeacher.dll」
那麼服務中心就會有變化
4、使用服務
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://localhost:3336/api/Student/GetList」
「http://localhost:3336/api/Student/GetModel?id=003」
屢次訪問「http://localhost:3336/api/Teacher/GetList」,則address會隨機切換,注意看返回的端口號
代碼:https://files.cnblogs.com/files/shousiji/netcore_wfw.rar