廬山真面目之十二微服務架構基於Docker搭建Consul集羣、Ocelot網關集羣和IdentityServer版本實現
html
1、簡介
在第七篇文章《廬山真面目之七微服務架構Consul集羣、Ocelot網關集羣和IdentityServer4版本實現》中,咱們已經探討了如何搭建基於Windows 環境的Consul服務集羣、Ocelot網關集羣和認證的微服務架構。咱們是否是這樣就算是完成了微服務架構的搭建了嗎?固然沒有了,生產環境中確定不會在Windows系統下搭建這些,之前只不過是測試的環境。從今天開始咱們將要微服務架構搬到Linux環境中去,而且是基於Docker來搭建的?今天這篇文章會很長,你們要有耐性。
1、說明
在看這篇文章以前,你們仍是要有些準備的。好比:會操做Linux系統,會使用Docker,基本操做要會,對Net5.0也要全部瞭解,也就是對跨平臺開發有所瞭解,還要有一些鏡像文件,好比:nginx,consul等等,還有其餘的一些基礎,你們都要熟悉,這些東西沒有辦法寫在這裏了。在此特別聲明:若是是高手的話,這些東西相對於您來講,確定是微不足道,請您口下留德,再者說,這些文章是爲零基礎的人寫的,不要擡槓了,若是有高見,也但願不靈賜教。特別說明,這裏的全部代碼都通過測試,因此你們能夠放心使用。
2、開發環境
如下就是開發環境,不用多說,都很簡單,一看就知道。
(1)、開發工具:Visual Studio 2019
(2)、開發語言:C#
(3)、開發平臺:Net 5.0和Net Core 3.1,跨平臺。
(4)、服務註冊:Consul集羣,服務註冊、發現中心
(5)、服務治理:Ocelot集羣,負載均衡、服務治理
(6)、網關服務:Nginx 服務組件,一個負載Consul服務,一個負載Ocelot網關。
(7)、操做系統:Linux(CentOS7)。
(8)、鑑權受權:IdentityServer4
3、咱們的目標
今天咱們的目標是,在Linux系統上搭建基於Docker來實現Consul集羣、Ocelot集羣和IdentityServer4鑑權、受權的微服務架構。這個任務比較艱鉅,篇幅必定很長,由於包含的內容有點多。固然這個確定不是最終版本,咱們還會繼續演化下去。
目標框架如圖:
node
2、搭建Consul服務的集羣。
Consul 用 Golang 實現,所以具備自然可移植性(支持 Linux、windows 和 Mac OS X ),它的安裝包僅包含一個可執行文件,方便部署,與 Docker 等輕量級容器可無縫配合。
在這裏咱們僅僅對Consul集羣作簡單的介紹,具體的詳情能夠本身去網上學習。Consul服務在Cluster集羣上的每個節點都運行一個Agent代理,這個Agent代理可使用Server服務器或者Client客戶端模式。Client客戶端負責到Server服務器端的高效通訊,相對爲無狀態的。 Server服務器端負責:包括選舉領導節點,維護Cluster集羣的狀態,對全部的查詢作出響應,跨數據中心的通訊等等。
Agent代理能夠運行在Server服務器模式或者Client客戶模式,每一個數據中心至少有一個Agent代理運行在server服務器模式,通常建議是3或者5個Server。部署單個Server是很是很差的,由於在失敗場景中出現數據丟失是不可避免的。咱們今天要3個服務器端和1個客戶端來完成咱們今天的架構任務。
名詞解釋:
A、Client :Consul 的 Client模式,就是客戶端模式。是 Consul 節點的一種模式,這種模式下,全部註冊到當前節點的服務會被轉發到 Server,自己不具備持久化數據的功能。
B、Server :Consul 的 Server 模式,代表這個 Consul 是個 Server ,這種模式下,功能和 Client 都同樣,惟一不一樣的是,它會把全部的數據持久化的本地,這樣遇到故障,信息是能夠被保留的。
C、Server-Leader:是全部服務器們的老大,它和其它 Server 不同的一點是,它須要負責同步註冊的信息給其它的 Server ,同時也要負責各個節點的健康監測。
D、Raft:Server 節點之間的數據一致性保證協議使用的是 raft,而 Zookeeper 用的 PAXOS,ETCD採用的也是Raft服務發現協議,Consul 採用 http 和 DNS 協議,ETCD 只支持 http 。
E、服務註冊:Consul 支持兩種方式實現服務註冊,一種是經過 Consul 的服務註冊API(Http協議),由服務本身調用 API 實現註冊;另外一種方式是經過 JSON 格式的配置文件實現註冊,將須要註冊的服務以 JSON 格式的配置文件給出。Consul 官方建議使用第二種方式。
Consul文檔:https://www.consul.io/docs
Consul官網:https://www.consul.io
咱們開始在Linux環境中基於Docker來搭建咱們的Consul服務集羣。
1、在Linux系統中,先查看咱們是否有Consul的鏡像,若是沒有就趕忙拉去吧。
命令:#docker images,我這裏沒有,我把環境清空了,因此我要從新拉取。
命令:#docker pull consul
2、開始啓動服務實例,3個服務器端實例,一個客戶端實例。
Client 客戶端,不會存儲數據。Server服務器端能夠固化數據,3個服務器端,實現 Raft算法,選舉出一個Leader。初始化須要3個Server服務器節點,選出Leader 服務器節點負責數據同步。若是隻有一個Server 節點,集羣會失敗。
參數解釋:
consul agent:命令頭,必需要有。
-server:表示要啓動服務器代理(agent)模式。Consul Agent節點的運行模式有兩種,Server模式和Client模式。其區別就是Server模式數據能夠持久化到本地,而Client模式不能夠。
-ui:consul運行後,會提供一個http://127.0.0.1:8500/ui/的網站,裏面存儲了Consul Agent各個節點以及註冊的服務等相關信息,即數據中心的網頁形式體現。這個參數表明是否建立這個網站,這個參數與這個數據中心網站有關。
-bind:本機的IP地址,集羣內其餘代理服務器能夠經過這個IP來訪問這臺電腦的consul代理服務器。
-bootstrap-expect:是集羣啓動條件,指當服務器端模式(Server模式)的代理達到這個數目後,纔開始運行。
-data-dir:是存放數據中心數據的目錄,該目錄必須是穩定的,系統重啓後也繼續存在的。
-config-dir:是存放數據中心日誌的目錄,該目錄必須是穩定的,系統重啓後也繼續存在的。
-datacenter:當前Consul的中心數據的名稱,默認是dc1。
-node:節點在集羣中的名稱,在一個集羣中必須是惟一的,默認是該節點的主機名(表明一個機器)。
-client:本地IP地址,這裏使用 0.0.0.0 ,就表示這個服務器全部IP均可以,即當這臺電腦有倆IP,192.168.1.100和192.168.1.111,那麼經過這倆IP均可以訪問到這臺機器的consul代理服務器。
-join:表示當前的服務器節點或者是客戶端節點要加入集羣的服務器,後面跟要加入的服務器的具體IP地址。
安裝完成後,Agent就能夠啓動了,咱們開始搭建咱們Consul集羣了。
(1)、啓動 Consul-Server-Leader 主節點。
命令:# docker run -d --name=masternode --restart=always -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt":true}' -p 8300:8300 -p 8301:8301 -p 8301:8301/udp -p 8302:8302/udp -p 8302:8302 -p 8400:8400 -p 8500:8500 -p 8600:8600 -h masternode consul agent -server -bind=0.0.0.0 -bootstrap-expect=3 -node=masternode -data-dir=/tmp/data-dir -client 0.0.0.0 -ui
nginx
1 docker run -d --name=masternode --restart=always \ 2 -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt":true}'\ 3 -p 8300:8300\ 4 -p 8301:8301\ 5 -p 8301:8301/udp\ 6 -p 8302:8302/udp\ 7 -p 8302:8302\ 8 -p 8400:8400\ 9 -p 8500:8500\ 10 -p 8600:8600\ 11 -h masternode\ 12 consul agent -server -bind=0.0.0.0 -bootstrap-expect=3 -node=masternode\ 13 -data-dir=/tmp/data-dir -client 0.0.0.0 -ui 14 15 Consul的地址:http://192.168.127.141:8500/
啓動:
效果:
(2)、建立Server- Follower,Consul集羣中的第一個追隨者
命令:# docker run -d --name=followernode --restart=always -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt":true}' -p 9300:8300 -p 9301:8301 -p 9301:8301/udp -p 9302:8302/udp -p 9302:8302 -p 9400:8400 -p 9500:8500 -p 9600:8600 -h followernode consul agent -server -bind=0.0.0.0 -join=192.168.127.141 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=followernode -data-dir=/tmp/data-dir -client 0.0.0.0 -ui算法
1 docker run -d --name=followernode --restart=always\ 2 -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt":true}'\ 3 -p 9300:8300\ 4 -p 9301:8301\ 5 -p 9301:8301/udp\ 6 -p 9302:8302/udp\ 7 -p 9302:8302\ 8 -p 9400:8400\ 9 -p 9500:8500\ 10 -p 9600:8600\ 11 -h followernode\ 12 consul agent -server -bind=0.0.0.0 -join=192.168.127.141\ 13 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=followernode\ 14 -data-dir=/tmp/data-dir -client 0.0.0.0 -ui 15 16 17 Consul的地址:http://192.168.127.141:9500/
啓動:
效果:
(3)、建立Server- Follower,Consul集羣中的第二個追隨者
命令:#docker run -d --name=followernode2 --restart=always -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt":true}' -p 10300:8300 -p 10301:8301 -p 10301:8301/udp -p 10302:8302/udp -p 10302:8302 -p 10400:8400 -p 10500:8500 -p 10600:8600 -h followernode2 consul agent -server -bind=0.0.0.0 -join=192.168.127.141 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=followernode2 -data-dir=/tmp/data-dir -client 0.0.0.0 -uidocker
1 docker run -d --name=followernode2 --restart=always\ 2 -e 'CONSUL_LOCAL_CONFIG={"skip_leave_on_interrupt":true}'\ 3 -p 10300:8300\ 4 -p 10301:8301\ 5 -p 10301:8301/udp\ 6 -p 10302:8302/udp\ 7 -p 10302:8302\ 8 -p 10400:8400\ 9 -p 10500:8500\ 10 -p 10600:8600\ 11 -h followernode2\ 12 consul agent -server -bind=0.0.0.0\ 13 -join=192.168.127.141 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=followernode2\ 14 -data-dir=/tmp/data-dir -client 0.0.0.0 -ui 15 16 Consul的地址:http://192.168.127.141:10500/
啓動:
效果:
(4)、建立Consul-Client ,Consul集羣中的客戶端。
命令:#docker run -d --name=clientNode --restart=always -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate":true}' -p 11300:8300 -p 11301:8301 -p 11301:8301/udp -p 11302:8302/udp -p 11302:8302 -p 11400:8400 -p 11500:8500 -p 11600:8600 -h clientNode consul agent -bind=0.0.0.0 -retry-join=192.168.127.141 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=clientNode -data-dir=/tmp/data-dir -client 0.0.0.0 -ui編程
1 docker run -d --name=clientnode --restart=always\ 2 -e 'CONSUL_LOCAL_CONFIG={"leave_on_terminate":true}'\ 3 -p 11300:8300\ 4 -p 11301:8301\ 5 -p 11301:8301/udp\ 6 -p 11302:8302/udp\ 7 -p 11302:8302\ 8 -p 11400:8400\ 9 -p 11500:8500\ 10 -p 11600:8600\ 11 -h clientnode\ 12 consul agent -bind=0.0.0.0 -retry-join=192.168.127.141\ 13 -node-id=$(uuidgen | awk '{print tolower($0)}') -node=clientnode\ 14 -data-dir=/tmp/data-dir -client 0.0.0.0 -ui 15 16 Consul的網站:http://192.168.127.141:11500/
啓動:
效果:
3、驗證3個服務器端和一個客戶端是否安裝成功。
執行這些命令,都要切換到Consul所在的目錄。切記。
(1)、執行命令查看容器實例。
命令:#docker ps –a
(2)、查看Consul成員列表,三個服務器端實例,一個客戶端實例。
命令:#docker exec -t clientnode consul members
3個server,1個client,狀態是:alive,說明集羣建立成功。
(3)、咱們在看看服務器角色的分配是否合適?一主二從,則表示運行成功。
命令:
#docker exec -t masternode consul operator raft list-peersjson
(4)、咱們也能夠經過瀏覽器訪問如下地址,驗證Consul服務是否安裝成功。
第一主服務器: http://192.168.127.141:8500
第二從服務器: http://192.168.127.141:9500
第三從服務器: http://192.168.127.141:10500
Consul客戶端: http://192.168.127.141:11500
能看到以下截圖,也能夠說明成功。我只截一個圖了,其餘都相似。
bootstrap
3、搭建微服務測試項目。
咱們要想搭建微服務架構,第一步,咱們固然要搭建咱們本身的測試項目了,代碼都很簡單,主要是爲了突出各個開源技術點。這是基礎中的基礎,沒有這一步,其餘的都是空中樓閣,沒有說服力了。廢話少說,咱們開始吧。
1、創建測試項目,並編寫各個項目的所需代碼。
(1)、PatrickLiu.MicroService.Client(ASP.NET CORE MVC),客戶端項目。
該項目模仿客戶端程序,固然能夠是你願意的任何客戶端程序,別擡槓,我這裏只是一個簡單的MVC項目,經過地址訪問微服務。
樣例代碼:
vim
1 using System; 2 using System.Collections.Generic; 3 using System.Net.Http; 4 using Microsoft.AspNetCore.Mvc; 5 using Microsoft.Extensions.Logging; 6 using PatrickLiu.MicroService.Interfaces; 7 using PatrickLiu.MicroService.Models; 8 9 namespace PatrickLiu.MicroService.Client.Controllers 10 { 11 public class HomeController : Controller 12 { 13 private readonly ILogger<HomeController> _logger; 14 private readonly IUserService _userService; 15 16 /// <summary> 17 /// 初始化該類型的新實例。 18 /// </summary> 19 /// <param name="logger">注入日誌對象。</param> 20 /// <param name="userService">注入用戶服務對象。</param> 21 public HomeController(ILogger<HomeController> logger, IUserService userService) 22 { 23 _logger = logger; 24 _userService = userService; 25 } 26 27 /// <summary> 28 /// 首頁。 29 /// </summary> 30 /// <returns></returns> 31 public IActionResult Index() 32 { 33 34 #region 經過 Ocelot 集羣網關訪問服務實例,追加訪問 Token,切記,我這裏沒寫。 35 36 string url = "http://192.168.127.141:8083/gate/users/all"; 37 38 #endregion 39 40 string content = InvokeAPI(url); 41 this.ViewBag.Users = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<User>>(content); 42 Console.WriteLine($"This is {url} Invoke."); 43 44 #endregion 45 46 return View(); 47 } 48 49 50 /// <summary> 51 /// 52 /// </summary> 53 /// <param name="url"></param> 54 /// <returns></returns> 55 public static string InvokeAPI(string url) 56 { 57 using (HttpClient client = new HttpClient()) 58 { 59 HttpRequestMessage message = new HttpRequestMessage(); 60 message.Method = HttpMethod.Get; 61 message.RequestUri = new Uri(url); 62 var result = client.SendAsync(message).Result; 63 string conent = result.Content.ReadAsStringAsync().Result; 64 return conent; 65 } 66 } 67 } 68 }
(2)、PatrickLiu.MicroService.Interfaces(NET CORE 類庫),定義服務接口,面向接口編程嘛,代碼很簡單,由於重點不是它。
樣例代碼: windows
1 using PatrickLiu.MicroService.Models; 2 using System.Collections.Generic; 3 4 namespace PatrickLiu.MicroService.Interfaces 5 { 6 /// <summary> 7 /// 用戶服務的接口定義。 8 /// </summary> 9 public interface IUserService 10 { 11 /// <summary> 12 /// 查找指定主鍵的用戶實例對象。 13 /// </summary> 14 /// <param name="id">用戶的主鍵。</param> 15 /// <returns>返回查找到的用戶實例對象。</returns> 16 User FindUser(int id); 17 18 /// <summary> 19 /// 獲取全部用戶的實例集合。 20 /// </summary> 21 /// <returns>返回全部的用戶實例。</returns> 22 IEnumerable<User> UserAll(); 23 } 24 }
(3)、PatrickLiu.MicroService.Models(NET CORE 類庫),定義實例類型,主要用於數據傳遞,代碼很簡單,由於重點不是它。
樣例代碼:
1 using System; 2 3 namespace PatrickLiu.MicroService.Models 4 { 5 /// <summary> 6 /// 用戶模型。 7 /// </summary> 8 public class User 9 { 10 /// <summary> 11 /// 獲取或者設置用戶主鍵。 12 /// </summary> 13 public int ID { get; set; } 14 15 /// <summary> 16 /// 獲取或者設置用戶姓名。 17 /// </summary> 18 public string Name { get; set; } 19 20 /// <summary> 21 /// 獲取或者設置用戶帳號名稱。 22 /// </summary> 23 public string Account { get; set; } 24 25 /// <summary> 26 /// 獲取或者設置用戶密碼。 27 /// </summary> 28 public string Password { get; set; } 29 30 /// <summary> 31 /// 獲取或者設置用戶的電子郵箱地址。 32 /// </summary> 33 public string Email { get; set; } 34 35 /// <summary> 36 /// 獲取或者設置用戶角色。 37 /// </summary> 38 public string Role { get; set; } 39 40 /// <summary> 41 /// 獲取或者設置用戶的登陸時間。 42 /// </summary> 43 public DateTime LoginTime { get; set; } 44 } 45 }
(4)、PatrickLiu.MicroService.Services(NET CORE 類庫),定義服務實現,咱們有了接口,而後基於接口實現具體的服務,代碼很簡單,由於重點不是它。
樣例代碼:
1 using PatrickLiu.MicroService.Interfaces; 2 using PatrickLiu.MicroService.Models; 3 using System; 4 using System.Collections.Generic; 5 using System.Linq; 6 7 namespace PatrickLiu.MicroService.Services 8 { 9 /// <summary> 10 /// 實現用戶服務接口的實現類型。 11 /// </summary> 12 public class UserService : IUserService 13 { 14 private IList<User> dataList; 15 16 /// <summary> 17 /// 初始化類型的實例 18 /// </summary> 19 public UserService() 20 { 21 dataList = new List<User>() 22 { new User {ID=1,Name="黃飛鴻",Account="HuangFeiHong",Password="HuangFeiHong123456",Email="huangFeiHong@sina.com", Role="Admin", LoginTime=DateTime.Now }, 23 new User {ID=2,Name="洪熙官",Account="HongXiGuan",Password="HongXiGuan54667",Email="HongXiGuan@sina.com", Role="Admin", LoginTime=DateTime.Now.AddDays(-5) }, 24 new User {ID=3,Name="方世玉",Account="FangShiYu",Password="FangShiYu112233",Email="fangShiYu@163.com", Role="Admin", LoginTime=DateTime.Now.AddDays(-30) }, 25 new User {ID=4,Name="苗翠花",Account="MiaoCuiHua",Password="MiaoCuiHua887766",Email="miaoCuiHua@sohu.com", Role="Admin", LoginTime=DateTime.Now.AddDays(-90) }, 26 new User {ID=5,Name="嚴詠春",Account="YanYongChun",Password="YanYongChun09392",Email="yanYongChun@263.com", Role="Admin", LoginTime=DateTime.Now.AddMinutes(-50) }}; 27 } 28 29 /// <summary> 30 /// 查找指定主鍵的用戶實例對象。 31 /// </summary> 32 /// <param name="id">用戶的主鍵。</param> 33 /// <returns>返回查找到的用戶實例對象。</returns> 34 public User FindUser(int id) 35 { 36 return dataList.FirstOrDefault(user => user.ID == id); 37 } 38 39 /// <summary> 40 /// 獲取全部用戶的實例集合。 41 /// </summary> 42 /// <returns>返回全部的用戶實例。</returns> 43 public IEnumerable<User> UserAll() 44 { 45 return dataList; 46 } 47 } 48 }
(5)、PatrickLiu.MicroService.ServiceInstance(ASP.NET CORE WEBAPI),這個就是咱們的服務,經過啓動多個實例,實現集羣,代碼很簡單,由於重點不是它。
這個項目必須引入其餘三個項目:
PatrickLiu.MicroService.Interfaces
PatrickLiu.MicroService.Models
PatrickLiu.MicroService.Services
【1】、安裝Consul服務組件,以支持註冊到Consul服務中心。
命令:Install-Package Consul
能夠在項目菜單【依賴項】菜單上點擊右鍵,選擇【管理 NuGet 程序包】來安裝Consul服務。
【2】、HealthController.cs,主要用於Consul服務的健康檢查。
樣例代碼:
1 using System; 2 using Microsoft.AspNetCore.Mvc; 3 using Microsoft.Extensions.Configuration; 4 5 namespace PatrickLiu.MicroService.ServiceInstance.Controllers 6 { 7 /// <summary> 8 /// 健康檢查的控制器。 9 /// </summary> 10 [ApiController] 11 [Route("api/[controller]")] 12 public class HealthController : ControllerBase 13 { 14 private IConfiguration _configuration; 15 16 /// <summary> 17 /// 初始化該類型的新實例。 18 /// </summary> 19 /// <param name="configuration">配置接口。</param> 20 public HealthController(IConfiguration configuration) 21 { 22 _configuration = configuration; 23 } 24 25 /// <summary> 26 /// 要調用的接口。 27 /// </summary> 28 [HttpGet] 29 [Route("Index")] 30 public IActionResult Index() 31 { 32 Console.WriteLine($"This is HealhController {_configuration["port"]} Invoke"); 33 return Ok(); 34 } 35 } 36 }
【3】、UsersController.cs,主要是業務類型,內容很簡單。
樣例代碼:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Threading; 5 using Microsoft.AspNetCore.Mvc; 6 using Microsoft.Extensions.Configuration; 7 using Microsoft.Extensions.Logging; 8 using PatrickLiu.MicroService.Interfaces; 9 using PatrickLiu.MicroService.Models; 10 11 namespace PatrickLiu.MicroService.ServiceInstance.Controllers 12 { 13 /// <summary> 14 /// 用戶的 API 類型。 15 /// </summary> 16 [Route("api/[controller]")] 17 [ApiController] 18 public class UsersController : ControllerBase 19 { 20 #region 私有字段 21 22 private readonly ILogger<UsersController> _logger; 23 private readonly IUserService _userService; 24 private IConfiguration _configuration; 25 26 #endregion 27 28 #region 構造函數 29 30 /// <summary> 31 /// 初始化該類型的新實例。 32 /// </summary> 33 /// <param name="logger">日誌記錄器。</param> 34 /// <param name="userService">用戶服務接口。</param> 35 /// <param name="configuration">配置服務。</param> 36 public UsersController(ILogger<UsersController> logger, IUserService userService, IConfiguration configuration) 37 { 38 _logger = logger; 39 _userService = userService; 40 _configuration = configuration; 41 } 42 43 #endregion 44 45 #region 實例方法 46 47 /// <summary> 48 /// 獲取一條記錄。 49 /// </summary> 50 /// <param name="id"></param> 51 /// <returns></returns> 52 [HttpGet] 53 [Route("Get")] 54 public User Get(int id) 55 { 56 return _userService.FindUser(id); 57 } 58 59 /// <summary> 60 /// 獲取全部記錄。 61 /// </summary> 62 /// <returns></returns> 63 [HttpGet] 64 [Route("All")] 65 public IEnumerable<User> Get() 66 { 67 Console.WriteLine($"This is UsersController {this._configuration["port"]} Invoke"); 68 69 return this._userService.UserAll().Select((user => new User 70 { 71 ID = user.ID, 72 Name = user.Name, 73 Account = user.Account, 74 Password = user.Password, 75 Email = user.Email, 76 Role = $"{this._configuration["ip"]}:{this._configuration["port"]}", 77 LoginTime = user.LoginTime 78 })); ; 79 } 80 81 /// <summary> 82 /// 超時處理,用於測試服務治理的超時管理。 83 /// </summary> 84 /// <returns></returns> 85 [HttpGet] 86 [Route("Timeout")] 87 public IEnumerable<User> Timeout() 88 { 89 Console.WriteLine($"This is Timeout Start"); 90 //超時設置。 91 Thread.Sleep(3000); 92 93 Console.WriteLine($"This is Timeout End"); 94 95 return this._userService.UserAll().Select((user => new User 96 { 97 ID = user.ID, 98 Name = user.Name, 99 Account = user.Account, 100 Password = user.Password, 101 Email = user.Email, 102 Role = $"{this._configuration["ip"]}:{this._configuration["port"]}", 103 LoginTime = user.LoginTime 104 })); ; 105 } 106 107 #endregion 108 } 109 }
【4】、增長擴展類型:ConsulExtension.cs
源碼以下:
1 using Consul; 2 using Microsoft.Extensions.Configuration; 3 using Microsoft.Extensions.Hosting; 4 using System; 5 6 namespace PatrickLiu.MicroService.ServiceInstance.Extensions 7 { 8 /// <summary> 9 /// Consul 靜態擴展類。 10 /// </summary> 11 public static class ConsulExtension 12 { 13 /// <summary> 14 ///類型初始化器,初始化 Consul 網址和數據中心。 15 /// </summary> 16 static ConsulExtension() 17 { 18 Uri = new Uri("http://localhost:8500"); 19 DataCenter = "dc1"; 20 } 21 22 /// <summary> 23 /// 獲取或者設置 Consul 的網址。 24 /// </summary> 25 public static Uri Uri { get; set; } 26 27 /// <summary> 28 /// 獲取或者設置數據中心。 29 /// </summary> 30 public static string DataCenter { get; set; } 31 32 /// <summary> 33 /// 向 Consul 服務中心註冊服務實例。 34 /// </summary> 35 /// <param name="configuration">配置對象。</param> 36 /// <param name="consulServiceName">在 Consul 服務中心註冊的服務類別名稱,多個實例的 ID 能夠屬於一個服務類別名稱。</param> 37 /// <param name="serviceID">服務實例的主鍵值,必須惟一。</param> 38 public static void ConsulRegist(this IConfiguration configuration, string consulServiceName, string serviceID) 39 { 40 if (string.IsNullOrEmpty(consulServiceName) || string.IsNullOrWhiteSpace(consulServiceName)) 41 { 42 throw new ArgumentNullException("consulServiceName is null"); 43 } 44 if (string.IsNullOrEmpty(serviceID) || string.IsNullOrWhiteSpace(serviceID)) 45 { 46 throw new ArgumentNullException("serviceID is null."); 47 } 48 49 string consulAddress = configuration["ConsulAddress"]; 50 string consulCenter = configuration["ConsulCenter"]; 51 if (!string.IsNullOrEmpty(consulAddress) && !string.IsNullOrWhiteSpace(consulAddress)) 52 { 53 Uri = new Uri(consulAddress); 54 } 55 56 if (!string.IsNullOrEmpty(consulCenter) && !string.IsNullOrWhiteSpace(consulCenter)) 57 { 58 DataCenter = consulCenter; 59 } 60 61 using (ConsulClient client = new ConsulClient(config => 62 { 63 config.Address = Uri; 64 config.Datacenter = DataCenter; 65 })) 66 { 67 string ip = configuration["ip"]; 68 int port = int.Parse(configuration["port"]); 69 int weight = string.IsNullOrWhiteSpace(configuration["weight"]) ? 1 : int.Parse(configuration["weight"]); 70 71 72 client.Agent.ServiceRegister(new AgentServiceRegistration() 73 { 74 ID = serviceID, 75 Name = consulServiceName, 76 Address = ip, 77 Port = port, 78 Tags = new string[] { weight.ToString() }, 79 Check = new AgentServiceCheck() 80 { 81 Interval = TimeSpan.FromSeconds(12), 82 HTTP = $"http://{ip}:{port}/API/Health/Index", 83 Timeout = TimeSpan.FromSeconds(5), 84 DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(20) 85 } 86 }).Wait(); 87 Console.WriteLine($"註冊服務:{ip}:{port}--Weight:{weight}"); 88 }; 89 } 90 91 /// <summary> 92 /// 向 Consul 服務中心註銷服務實例。 93 /// </summary> 94 /// <param name="applicationLifetime">配置對象。</param> 95 /// <param name="serviceID">服務實例的主鍵值,必須惟一。</param> 96 public static void ConsulDown(this IHostApplicationLifetime applicationLifetime, string serviceID) 97 { 98 if (string.IsNullOrEmpty(serviceID) || string.IsNullOrWhiteSpace(serviceID)) 99 { 100 throw new ArgumentNullException("serviceID is null"); 101 } 102 applicationLifetime.ApplicationStopped.Register(() => 103 { 104 using (var consulClient = new ConsulClient(config => { config.Address = Uri; config.Datacenter = DataCenter; })) 105 { 106 Console.WriteLine("服務已經退出"); 107 consulClient.Agent.ServiceDeregister(serviceID); 108 } 109 }); 110 } 111 } 112 }
【5】、修改 Startup.cs 類的 Configure 方法的代碼。
源碼以下:
1 using Microsoft.AspNetCore.Builder; 2 using Microsoft.AspNetCore.Hosting; 3 using Microsoft.Extensions.Configuration; 4 using Microsoft.Extensions.DependencyInjection; 5 using Microsoft.Extensions.Hosting; 6 using PatrickLiu.MicroService.Interfaces; 7 using PatrickLiu.MicroService.ServiceInstance.Extensions; 8 using PatrickLiu.MicroService.Services; 9 using System; 10 11 namespace PatrickLiu.MicroService.ServiceInstance 12 { 13 /// <summary> 14 /// 應用程序啓動配置。 15 /// </summary> 16 public class Startup 17 { 18 /// <summary> 19 /// 構造函數注入配置對象。 20 /// </summary> 21 /// <param name="configuration">配置對象</param> 22 public Startup(IConfiguration configuration) 23 { 24 Configuration = configuration; 25 } 26 27 /// <summary> 28 ///獲取配置對象實例。 29 /// </summary> 30 public IConfiguration Configuration { get; } 31 32 /// <summary> 33 /// 配置注入容器的實例。 34 /// </summary> 35 /// <param name="services"></param> 36 public void ConfigureServices(IServiceCollection services) 37 { 38 services.AddControllers(); 39 services.AddSingleton<IUserService, UserService>(); 40 } 41 42 /// <summary> 43 /// 配置 Http處理的管道。 44 /// </summary> 45 /// <param name="app">應用程序生成器。</param> 46 /// <param name="env">Web宿主環境。</param> 47 /// <param name="applicationLifetime">宿主應用程序的生命週期。</param> 48 public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IHostApplicationLifetime applicationLifetime) 49 { 50 #region 中間件配置 51 52 if (env.IsDevelopment()) 53 { 54 app.UseDeveloperExceptionPage(); 55 } 56 57 //app.UseHttpsRedirection(); 58 59 app.UseRouting(); 60 61 //增長認證環節 62 app.UseAuthentication();//認證=============================== 63 64 app.UseAuthorization();//受權 65 66 app.UseEndpoints(endpoints => 67 { 68 endpoints.MapControllers(); 69 }); 70 71 #endregion 72 73 #region Consul 註冊 74 75 string serviceID = $"Service:{Configuration["ip"]}:{Configuration["port"]}---{Guid.NewGuid()}"; 76 string consuleServiceName = "PatrickLiuService"; 77 78 //註冊服務。 79 Configuration.ConsulRegist(consuleServiceName, serviceID); 80 81 //註銷服務 82 applicationLifetime.ConsulDown(serviceID); 83 84 #endregion 85 } 86 } 87 }
【6】、增長4個配置JSON文件。
appsettings5726.json
appsettings5727.json
appsettings5728.json
appsettings5729.json
【7】、增長docker-compose.yml批處理了文件。
代碼以下:
1 version: '3.3' 2 services: 3 service1: 4 container_name: serviceInstance_5726 5 environment: 6 - ASPNETCORE_ENVIRONMENT=Production 7 build: 8 context: /root/microService/sourceCode/project/PatrickLiu.MicroService.Docker 9 image: compose-net5.0v1.202125 10 ports: 11 - 5726:80/tcp 12 volumes: 13 - /root/microService/config/appsettings/appsettings5726.json:/app/appsettings.json 14 15 service2: 16 container_name: serviceInstance_5727 17 environment: 18 - ASPNETCORE_ENVIRONMENT=Production 19 image: compose-net5.0v1.202125 20 ports: 21 - 5727:80/tcp 22 command: ["dotnet","/app/publish/PatrickLiu.MicroService.ServiceInstance.dll"] 23 volumes: 24 - /root/microService/config/appsettings/appsettings5727.json:/app/appsettings.json 25 26 service3: 27 container_name: serviceInstance_5728 28 environment: 29 - ASPNETCORE_ENVIRONMENT=Production 30 image: compose-net5.0v1.202125 31 ports: 32 - 5728:80/tcp 33 command: ["dotnet","/app/publish/PatrickLiu.MicroService.ServiceInstance.dll"] 34 volumes: 35 - /root/microService/config/appsettings/appsettings5728.json:/app/appsettings.json 36 37 service4: 38 container_name: serviceInstance_5729 39 environment: 40 - ASPNETCORE_ENVIRONMENT=Production 41 image: compose-net5.0v1.202125 42 ports: 43 - 5729:80/tcp 44 command: ["dotnet","/app/publish/PatrickLiu.MicroService.ServiceInstance.dll"] 45 volumes: 46 - /root/microService/config/appsettings/appsettings5729.json:/app/appsettings.json
(6)、PatrickLiu.MicroService.Gateway(ASP.NET CORE WEBAPI),網關服務。
【1】、安裝Ocelot組件,能夠實現針對服務管理工做,如:緩存等。
在【程序包管理器控制檯】執行命令
命令:Install-Package Ocelot
固然也能夠在項目下的【依賴項】上點右鍵,點擊【管理NuGet程序包】菜單,在【瀏覽】項先安裝,輸入Ocelot,在右側安裝則能夠。
【2】、安裝Ocelot.Provider.Consul組件,以實現Ocelot和Consul的組合。
在【程序包管理器控制檯】執行命令。
命令:Install-Package Ocelot.Provider.Consul
固然也能夠在項目下的【依賴項】上點右鍵,點擊【管理NuGet程序包】菜單,在【瀏覽】項先安裝,輸入Ocelot.Provider.Consul,在右側安裝則能夠。
【3】、配置Startup.cs文件。
源碼以下:
1 using IdentityServer4.AccessTokenValidation; 2 using Microsoft.AspNetCore.Builder; 3 using Microsoft.AspNetCore.Hosting; 4 using Microsoft.Extensions.Configuration; 5 using Microsoft.Extensions.DependencyInjection; 6 using Ocelot.Cache.CacheManager; 7 using Ocelot.DependencyInjection; 8 using Ocelot.Middleware; 9 using Ocelot.Provider.Consul; 10 using Ocelot.Provider.Polly; 11 12 namespace PatrickLiu.MicroService.Gateway 13 { 14 /// <summary> 15 /// 一、Ocelot 提供網關功能 16 /// 二、Ocelot.Provider.Polly 提供服務治理 17 /// 三、Ocelot.Provider.Consul 提供服務發現 18 /// 四、Ocelot.Cache.CacheManager 提供緩存功能。 19 /// </summary> 20 public class Startup 21 { 22 /// <summary> 23 /// 經過構造函數初始化配置對象。 24 /// </summary> 25 /// <param name="configuration">配置對象。</param> 26 public Startup(IConfiguration configuration) 27 { 28 Configuration = configuration; 29 } 30 31 /// <summary> 32 /// 獲取配置對象。 33 /// </summary> 34 public IConfiguration Configuration { get; } 35 36 /// <summary> 37 /// 配置服務。 38 /// </summary> 39 /// <param name="services">服務容器。</param> 40 public void ConfigureServices(IServiceCollection services) 41 { 42 #region 一、在網關中增長鑑權模塊 43 44 var authenticationProviderKey = "UserGatewayKey"; 45 services.AddAuthentication("Bearer") 46 .AddIdentityServerAuthentication(authenticationProviderKey, options => 47 { 48 options.Authority = "http://192.168.127.141:7200"; 49 options.ApiName = "UserApi"; 50 options.RequireHttpsMetadata = false; 51 options.SupportedTokens = SupportedTokens.Both; 52 }); 53 54 #endregion 55 56 #region 二、配置網關、網關緩存和服務治理 57 58 services.AddOcelot()//使用 Ocelot 網關服務。 59 .AddConsul()//使用Consul 服務發現控制器。 60 .AddCacheManager(builer => builer.WithDictionaryHandle()) //使用 Ocelot 緩存服務 61 .AddPolly();//支持瞬態故障庫----超時、熔斷、限流、降級、雪崩效應等均可以作 62 63 #endregion 64 } 65 66 /// <summary> 67 /// 配置中間件。 68 /// </summary> 69 /// <param name="app">應用程序生成器。</param> 70 /// <param name="env">Web宿主環境。</param> 71 public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 72 { 73 app.UseOcelot();//配置使用 Ocelot 網關中間件。 74 } 75 } 76 }
【4】、增長JSON配置文件,文件名:configuration.json。
源碼以下:
1 //四、************************************* Ocelot 網關 + Consul 服務發現 ************************************* 2 "Routes": [ 3 { 4 "DownstreamPathTemplate": "/api/{url}", 5 "DownstreamScheme": "http", 6 "UpstreamPathTemplate": "/gate/{url}", 7 "UpstreamHttpMethod": [ "Get", "Post" ], 8 "UseServiceDiscovery": true, 9 "ServiceName": "PatrickLiuService", 10 "LoadBalancerOptions": { "Type": "RoundRobin" } 11 } 12 ], 13 "GlobalConfiguration": { 14 "BaseUrl": "http://192.168.127.141:6299", 15 "ServiceDiscoveryProvider": { 16 "Host": "192.168.127.141", 17 "Port": 8089, 18 "Type": "Consul", 19 "PollingInterval": 1000,//輪訓 Consul,頻率毫秒 20 "Token": "footoken"//須要ACL的話 21 } 22 }
【5】、修改 Program.cs 文件,使用上面增長的JSON配置文件。
(7)、PatrickLiu.MicroService.AuthenticationCenter(ASP.NET CORE WEBAPI),鑑權、受權中心,也能夠稱「認證服務器」。
【1】、要想認證,必須安裝IdentityServer4。
命令:Install-Package IdentityServer4
固然也能夠在項目下的【依賴項】上點右鍵,點擊【管理NuGet程序包】菜單,在【瀏覽】項先安裝,輸入IdentityServer4,在右側安裝則能夠。
【2】、修改 Startup.cs文件。
【3】、增長一個類型 ClientInitConfig.cs文件。
代碼樣例:
1 using IdentityServer4.Models; 2 using System.Collections.Generic; 3 4 namespace PatrickLiu.MicroService.AuthenticationCenter 5 { 6 /// <summary> 7 /// 8 /// </summary> 9 public class ClientInitConfig 10 { 11 /// <summary> 12 /// 13 /// </summary> 14 /// <returns></returns> 15 public static IEnumerable<ApiScope> GetApiScopes() 16 { 17 return new List<ApiScope> 18 { 19 //User API 20 new ApiScope(name: "User.Get", displayName: "獲取用戶數據"), 21 22 // Health API 23 new ApiScope(name: "Health.Check", displayName: "健康檢查."), 24 }; 25 } 26 27 /// <summary> 28 /// 能訪問的資源權限。 29 /// </summary> 30 /// <returns></returns> 31 public static IEnumerable<ApiResource> GetApiResources() 32 { 33 return new List<ApiResource> 34 { 35 new ApiResource("UserApi","Invoice API") 36 { 37 Scopes={ "User.Get", "Health.Check" } 38 } 39 }; 40 } 41 42 43 /// <summary> 44 /// 客戶端的認證條件。 45 /// </summary> 46 /// <returns></returns> 47 public static IEnumerable<Client> GetClients() 48 { 49 return new List<Client> { 50 new Client{ 51 ClientId="PatrickLiu.MicroService.AuthenticationDemo", 52 ClientSecrets={new Secret("PatrickLiu123456".Sha256()) }, 53 AllowedGrantTypes=GrantTypes.ClientCredentials, 54 AllowedScopes=new[]{ "User.Get", "Health.Check" }, 55 Claims=new List<ClientClaim>(){ 56 new ClientClaim(IdentityModel.JwtClaimTypes.Role,"Admin"), 57 new ClientClaim(IdentityModel.JwtClaimTypes.NickName,"PatrickLiu"), 58 new ClientClaim("eMail","PatrickLiu@sina.com") 59 } 60 } 61 }; 62 } 63 } 64 }
2、編譯【PatrickLiu.MicroService.ServiceInstance】項目,發佈4個服務實例,獨立進程承載,造成服務集羣。
再次提醒你們,在開始啓動這4個服務實例以前,必須啓動Consul服務中心。
(1)、將【PatrickLiu.MicroService.ServiceInstance】項目編譯無誤後,而後將項目源碼上傳至Linux服務器。
服務器路徑爲:/root/microService/sourceCode/project
(2)、爲【PatrickLiu.MicroService.ServiceInstance】項目增長4個appsettings.json配置文件,並將配置文件上傳至Linux服務器。
服務器路徑爲:/root/microService/config/appsettings
(3)、爲【PatrickLiu.MicroService.ServiceInstance】項目增長Nginx配置文件,並上傳至Linux服務器。
服務器路徑爲:/root/microService/config/nginx
(4)、爲【PatrickLiu.MicroService.ServiceInstance】項目增長docker-compose.yml配置文件,並上傳至Linux服務器。該文件通常建議存放在項目的根目錄,若是存在解決方案,則存放在解決方案的根目錄。
服務器路徑爲:/root/microService/sourceCode/project/PatrickLiu.MicroService.Docker
Docker-Compose.yml文件的內容:
1 version: '3.3' 2 services: 3 service1: 4 container_name: serviceInstance_5726 5 environment: 6 - ASPNETCORE_ENVIRONMENT=Production 7 build: 8 context: /root/microService/sourceCode/project/PatrickLiu.MicroService.Docker 9 image: compose-net5.0v1.202125 10 ports: 11 - 5726:80/tcp 12 volumes: 13 - /root/microService/config/appsettings/appsettings5726.json:/app/appsettings.json 14 15 service2: 16 container_name: serviceInstance_5727 17 environment: 18 - ASPNETCORE_ENVIRONMENT=Production 19 image: compose-net5.0v1.202125 20 ports: 21 - 5727:80/tcp 22 command: ["dotnet","/app/publish/PatrickLiu.MicroService.ServiceInstance.dll"] 23 volumes: 24 - /root/microService/config/appsettings/appsettings5727.json:/app/appsettings.json 25 26 service3: 27 container_name: serviceInstance_5728 28 environment: 29 - ASPNETCORE_ENVIRONMENT=Production 30 image: compose-net5.0v1.202125 31 ports: 32 - 5728:80/tcp 33 command: ["dotnet","/app/publish/PatrickLiu.MicroService.ServiceInstance.dll"] 34 volumes: 35 - /root/microService/config/appsettings/appsettings5728.json:/app/appsettings.json 36 37 service4: 38 container_name: serviceInstance_5729 39 environment: 40 - ASPNETCORE_ENVIRONMENT=Production 41 image: compose-net5.0v1.202125 42 ports: 43 - 5729:80/tcp 44 command: ["dotnet","/app/publish/PatrickLiu.MicroService.ServiceInstance.dll"] 45 volumes: 46 - /root/microService/config/appsettings/appsettings5729.json:/app/appsettings.json
(5)、爲【PatrickLiu.MicroService.ServiceInstance】項目增長Dockerfile配置文件,並將該配置文件上傳至服務器,建議該文件存放在項目根目錄,若是是解決方案,那就存放在解決方案的根目錄。
服務器路徑爲:/root/microService/sourceCode/project/PatrickLiu.MicroService.Docker
Dockerfile文件的內容:
1 #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. 2 3 FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base 4 WORKDIR /app 5 EXPOSE 80 6 EXPOSE 443 7 8 FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build 9 WORKDIR /src 10 COPY ["PatrickLiu.MicroService.ServiceInstance/PatrickLiu.MicroService.ServiceInstance.csproj", "PatrickLiu.MicroService.ServiceInstance/"] 11 COPY ["PatrickLiu.MicroService.Interfaces/PatrickLiu.MicroService.Interfaces.csproj", "PatrickLiu.MicroService.Interfaces/"] 12 COPY ["PatrickLiu.MicroService.Models/PatrickLiu.MicroService.Models.csproj", "PatrickLiu.MicroService.Models/"] 13 COPY ["PatrickLiu.MicroService.Services/PatrickLiu.MicroService.Services.csproj", "PatrickLiu.MicroService.Services/"] 14 RUN dotnet restore "PatrickLiu.MicroService.ServiceInstance/PatrickLiu.MicroService.ServiceInstance.csproj" 15 COPY . . 16 WORKDIR "/src/PatrickLiu.MicroService.ServiceInstance" 17 RUN dotnet build "PatrickLiu.MicroService.ServiceInstance.csproj" -c Release -o /app/build 18 19 FROM build AS publish 20 RUN dotnet publish "PatrickLiu.MicroService.ServiceInstance.csproj" -c Release -o /app/publish 21 22 FROM base AS final 23 WORKDIR /app 24 COPY --from=publish /app/publish . 25 ENTRYPOINT ["dotnet", "PatrickLiu.MicroService.ServiceInstance.dll"]
(6)、經過docker-compose up 命令,啓動4個服務實例和一個NGINX服務。執行 docker-compose up 命令,必須在docker-compose.yml文件所在的目錄,docker-compose.yml和dockerfile兩個文件最好都放在一個目錄裏,建議都存放在項目或者解決方案的根目錄裏。
命令:# docker-compose up –d,執行命令,後臺運行,必須確保本地有Net5.0鏡像,Net5.0的官方鏡像拉取太慢,若是想提高鏡像拉取速度,請查看個人文章《我教你如何解決 Docker 下載 mcr.microsoft.com 鏡像慢的辦法》。
(7)、檢查服務是否啓動成功,是否正確註冊Consul服務。
訪問地址:http://192.168.127.141:8500
http://192.168.127.141:9500
http://192.168.127.141:10500
http://192.168.127.141:11500
任何一個地址均可以訪問。
(8)、全部服務都啓動成功,包括Consul集羣和4個服務實例一個Nginx服務。
(9)、配置Consul集羣的Nginx代理服務,修改Nginx.conf配置文件。
服務器路徑:/root/microService/config/consulNginx
修改配置文件:nginx.conf,進入當前目錄,執行命令:vim nginx.conf
(10)、啓動Consul集羣的代理服務Nginx服務。
命令:#docker run -d -p 8089:80 -v /root/microService/config/consulNginxLog/:/var/log/nginx/ -v /root/microService/config/consulNginx/nginx.conf:/etc/nginx/nginx.conf --name consulnginx nginx
參數1:/root/microService/config/consulNginxLog/:/var/log/nginx/ 經過掛載將容器裏面路徑:/var/log/nginx/的nginx日誌映射到容器外的這個目錄:/root/microService/config/consulNginxLog/ 。
參數2:/root/microService/config/consulNginx/nginx.conf:/etc/nginx/nginx.conf 經過掛載文件用/root/microService/config/consulNginx/nginx.conf配置文件來替換/etc/nginx/nginx.conf配置文件。
(11)、驗證Consul集羣的 Nginx 地址是否有效。
訪問地址:http://192.168.127.141:8089/
三、編譯【PatrickLiu.MicroService.Gateway】項目,發佈3個網關服務實例,獨立進程承載,造成服務集羣。
(1)、爲【PatrickLiu.MicroService.Gateway】項目增長Dockerfile文件,該文件上傳到Linux服務器。該文件能夠放到項目根目錄,若是有解決方案就放在解決方案的根目錄。
服務器路徑:/root/microService/sourceCode/gateway
Dockerfile文件的內容:
若是使用官方的鏡像,會報一下錯誤,內容不少,只是部分截圖:
Dockerfile文件增長的內容,兩者選其一:
FROM mcr.microsoft.com/dotnet/sdk:5.0-alpine(慢點)
FROM mcr.microsoft.com/dotnet/sdk:5.0-focal
(2)、爲【PatrickLiu.MicroService.Gateway】項目增長docker-compose.yml文件,該文件上傳到Linux服務器。該文件能夠放到項目根目錄,若是有解決方案就放在解決方案的根目錄。
服務器路徑:/root/microService/sourceCode/gateway
Docker-Compose.yml文件內容:
源碼以下:
1 version: '3.3' 2 services: 3 service1: 4 container_name: serviceOcelot_6297_GateWay 5 environment: 6 - ASPNETCORE_ENVIRONMENT=Production 7 build: 8 context: /root/microService/sourceCode/gateway 9 dockerfile: PatrickLiu.MicroService.Gateway/Dockerfile 10 image: compose-net5.0v1.202125-gateway 11 ports: 12 - 6297:80/tcp 13 14 service2: 15 container_name: serviceOcelot_6298_GateWay 16 environment: 17 - ASPNETCORE_ENVIRONMENT=Production 18 image: compose-net5.0v1.202125-gateway 19 ports: 20 - 6298:80/tcp 21 command: ["dotnet","/app/publish/PatrickLiu.MicroService.Gateway.dll"] 22 23 service3: 24 container_name: serviceOcelot_6299_GateWay 25 environment: 26 - ASPNETCORE_ENVIRONMENT=Production 27 image: compose-net5.0v1.202125-gateway 28 ports: 29 - 6299:80/tcp 30 command: ["dotnet","/app/publish/PatrickLiu.MicroService.Gateway.dll"] 31 32 nginx: 33 container_name: serviceOcelotNginx_8083_GateWay 34 image: nginx:latest 35 ports: 36 - 8083:80/tcp 37 restart: always 38 volumes: 39 - /root/microService/config/gatewayNginx/nginx.conf:/etc/nginx/nginx.conf
(3)、爲【PatrickLiu.MicroService.Gateway】項目增長configuration.json配置文件,該文件上傳到Linux服務器。
(4)、使用docker-compose up -d 命令進行批處理,啓動3個網關實例和一個NGINX服務。在執行該命令以前,必須切換到docker-compose.yml文件所在的目錄,而且dockerfile文件也要在當前目錄下。
命令:#docker-compose up –d
中間還有不少內容,省略了。。。
(5)、咱們網關啓動完成後,能夠經過docker-compose ps命令查看服務是否啓動正常,執行該命令必須在docker-compose.yml文件所在的目錄,切記。
命令:#docker-compose ps
(6)、開始驗證,在客戶端訪問咱們的客戶端是否能夠得到數據(這裏本地數據)。
第一網關地址:http://192.168.127.141:6297/gate/users/all,能獲取到數據表示一切成功。
截圖以下:
刷新地址
第二網關地址:http://192.168.127.141:6298/gate/users/all,能獲取到數據表示一切成功。
截圖以下:
刷新地址
第三網關地址:http://192.168.127.141:6299/gate/users/all,能獲取到數據表示一切成功。
截圖以下:
刷新地址
(7)、Ocelot網關集羣的Nginx服務已經在Docker-compose.yml配置啓動。
目錄地址:/root/microService/config/gatewayNginx/nginx.conf
配置信息:
如下是docker-compose.yml有關nginx配置。
(8)、驗證Ocelot網關集羣的Nginx服務地址。
Nginx地址:http://192.168.127.141:8083/gate/users/all,能獲取到數據表示一切成功。
截圖以下:
刷新地址後
完美完成負載均衡,內心有些小激動。說明:客戶端程序要訪問的地址就是這個地址:http://192.168.127.141:8083/gate/users/all
四、編譯【PatrickLiu.MicroService.AuthenticationCenter】項目,發佈鑑權、受權中心實例,獨立進程承載,造成服務集羣。
(1)、將【PatrickLiu.MicroService.AuthenticationCenter】項目源碼上傳到Linux服務器,並將Dockerfile文件存放在更目錄。
Dockerfile 文件內容:
(2)、將【PatrickLiu.MicroService.AuthenticationCenter】項目生成鏡像文件,切換到Dockerfile文件所在目錄,執行生成鏡像的命令。
命令:#docker build --no-cache -t authentor3.0v202127 -f Dockerfile .
中間省略不少步驟。。。
(3)、查看咱們生成鑑權中心的鏡像。
命令:#docker images
(4)、查看咱們生成鑑權中心的鏡像。
命令:#docker run -itd -p 7200:80 authentor3.0v202127
(5)、查看咱們生成鑑權中心的容器實例。
命令:#dockder ps –a
(6)、經過PostMan來測試咱們鑑權中心是否正常運行。
post 請求 http://192.168.127.141:7200/connect/token
(7)、咱們的網關設置了權限,如今要訪問就要增長token,不然無權訪問,返回403。
(8)、基於Jwt.io網站驗證Token數據。
訪問地址:https://jwt.io/
3、在Linux系統中基於Docker容器搭建的微服務,咱們經過客戶端來看一下效果。
一、全部環境都在虛擬機上,客戶端程序在本地,看看我辛苦的成果吧。
客戶端咱們本身實現的輪訓策略,每次刷新,端口號都變,效果如圖:
5726端口的數據:
5727端口的數據:
5728端口的數據:
5729端口的數據:
2、咱們的結論。
咱們今天的測試雖然完成了,可是仍是有不少要改進的地方,好比不少地方咱們均可以使用Docker-Compose代替Dockerfile文件,單節點的Docker環境也是問題,能夠把環境遷到K8s上,還有其餘不少問題,這不是咱們最後一版,咱們繼續努力,完善它。
4、結束語 好了,今天就寫到這裏了。這篇文章也花費了我兩週的時間,解決NetCore3.1到Net5.0上所遇到的問題,坑真實很多。在Docker環境中部署東西,或者說在虛擬環境中部署東西,是有一些不同的,有好處,固然也有弊端。不作不知道,作了才知道問題的多多。俗話說,兵來將擋水來土掩,只要咱們一往無前,道路必定是光明的,再者說,老天不會餓死努力的小鳥的。努力吧,天天進步一點點。