当前位置:网站首页>廬山真面目之二微服務架構NGINX版本實現
廬山真面目之二微服務架構NGINX版本實現
2020-11-07 16:46:00 【itread01】
一、簡介
在上一篇文章《廬山真面目之微服務的簡介和技術棧》中,我們已經探討了微服務的來龍去脈,也說了想要實現微服務架構所需要的技術棧,今天我們開始實現一個微服務,當然這個實現是簡化版本的,在這個版本里面也不涉及 Docker、K8S等的東西,我們逐步演化,今天這一期只是實現一個NGINX版本的微服務的功能。
1、說明
有關微服務架構所涉及的技術太多,無法再一篇文章內討論完全,所以,我們就分多期來說,每期都遞進相關的技術,然後,一步一步的演化而來。如果您是大牛,就可以直接跳過,因為這些東西相對於您來說,這個太簡單了。特別說明,這裡的所有程式碼都經過測試,所以大家可以放心使用。
2、開發環境
以下就是開發環境,不用多說,都很簡單,一看就知道。
(1)、開發工具:Visual Studio 2019
(2)、開發語言:C#
(3)、開發平臺:Net Core3.1,跨平臺。
(4)、閘道器服務:NGINX,專注於高效能閘道器。
3、今天的目標
今天我們的目標就是建立一個基於Nginx閘道器實現的,服務例項沒有任何容器包容,只是獨立程序承載的這麼一個架構實現。
二、微服務架構之NGINX 版本實現
在文章開始之前,我們還是要簡要說明一下。上一篇檔案《廬山真面目之微服務的簡介和技術棧》中我們說過,微服務有三個版本,分別是:單體架構、垂直拆分設計和微服務,基於SOA的我們暫時不討論。其實,第二版本和第一個沒有本質區別,都是單體架構而已,所以,我們今天就簡單實現一下微服務的版本,由於裡面涉及的技術很多,微服務這個版本我又分了多個版本來寫,今天是最簡單。
今天我們主要討論基於NGINX實現的分散式、微服務架構的優缺點,每個專案的程式碼都獨立貼出來,邏輯很簡單,因為我們側重架構嘛,我們開始吧。
1、我們解決方案,包含5個專案。
(1)、PatrickLiu.MicroService.Client(ASP.NET CORE MVC),客戶端應用程式。
這個專案很簡單,幾乎沒有任何修改,只是在這裡訪問服務例項而已。
1)、startup.cs 類中唯一增加的程式碼
1 public class Startup 2 { 3 4 /// <summary> 5 /// 註冊服務到容器中。 6 /// </summary> 7 /// <param name="services"></param> 8 public void ConfigureServices(IServiceCollection services) 9 { 10 services.AddSingleton<IUserService, UserService>(); 11 } 12 }
2)、HomeController.cs 類的程式碼
1 public class HomeController : Controller 2 { 3 private readonly ILogger<HomeController> _logger; 4 private readonly IUserService _userService; 5 private static int index; 6 7 /// <summary> 8 /// 初始化該型別的新例項。 9 /// </summary> 10 /// <param name="logger">注入日誌物件。</param> 11 /// <param name="userService">注入使用者服務物件。</param> 12 public HomeController(ILogger<HomeController> logger, IUserService userService) 13 { 14 _logger = logger; 15 _userService = userService; 16 } 17 18 /// <summary> 19 /// 首頁。 20 /// </summary> 21 /// <returns></returns> 22 public IActionResult Index() 23 { 24 #region 1、單體架構 25 26 //this.ViewBag.Users = _userService.UserAll(); 27 28 #endregion 29 30 #region 2、分散式架構 31 32 #region 2.1、直接訪問服務例項 33 34 //string url = string.Empty; 35 //url = "http://localhost:5726/api/users/all"; 36 //url = "http://localhost:5726/api/users/all"; 37 //url = "http://localhost:5726/api/users/all"; 38 39 #endregion 40 41 #region 通過 Ngnix閘道器訪問服務例項,預設輪訓。 42 43 string url = "http://localhost:8080/api/users/all"; 44 45 #endregion 46 47 string content = InvokeAPI(url); 48 this.ViewBag.Users = Newtonsoft.Json.JsonConvert.DeserializeObject<IEnumerable<User>>(content); 49 Console.WriteLine($"This is {url} Invoke."); 50 51 #endregion 52 53 return View(); 54 } 55 56 57 /// <summary> 58 /// 59 /// </summary> 60 /// <param name="url"></param> 61 /// <returns></returns> 62 public static string InvokeAPI(string url) 63 { 64 using (HttpClient client = new HttpClient()) 65 { 66 HttpRequestMessage message = new HttpRequestMessage(); 67 message.Method = HttpMethod.Get; 68 message.RequestUri = new Uri(url); 69 var result = client.SendAsync(message).Result; 70 string conent = result.Content.ReadAsStringAsync().Result; 71 return conent; 72 } 73 } 74 } 75 }
3)、Index.cshtml 檢視的程式碼
1 @{ 2 ViewData["Title"] = "Home Page"; 3 } 4 5 <div class="text-center"> 6 <h1 class="display-4">Welcome</h1> 7 <ul> 8 @{ 9 10 foreach (var item in ViewBag.Users) 11 { 12 <li>@item.ID [email protected] [email protected] </li> 13 } 14 } 15 </ul> 16 <p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p> 17 </div>
(2)、PatrickLiu.MicroService.Interfaces(NETCORE類庫專案),定義服務介面。
這個專案很簡單,只定義了一個介面型別,名稱:IUserService.cs。
IUserService的程式碼
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 (NETCORE類庫專案),定義實體類模型。
這個專案很簡單,只定義了一個實體型別,類名:User.cs。
User.cs 的程式碼
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(NetCore 類庫專案),實現介面型別。
這個專案很簡單,只定義了一個型別,實現IUserService介面,類名:UserService.cs。
UserService.cs的程式碼
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="[email protected]", Role="Admin", LoginTime=DateTime.Now }, 23 new User {ID=2,Name="洪熙官",Account="HongXiGuan",Password="HongXiGuan54667",Email="[email protected]", Role="Admin", LoginTime=DateTime.Now.AddDays(-5) }, 24 new User {ID=3,Name="方世玉",Account="FangShiYu",Password="FangShiYu112233",Email="[email protected]", Role="Admin", LoginTime=DateTime.Now.AddDays(-30) }, 25 new User {ID=4,Name="苗翠花",Account="MiaoCuiHua",Password="MiaoCuiHua887766",Email="[email protected]", Role="Admin", LoginTime=DateTime.Now.AddDays(-90) }, 26 new User {ID=5,Name="嚴詠春",Account="YanYongChun",Password="YanYongChun09392",Email="[email protected]", 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 WEB API專案)。
這個專案很簡單,引用其他三個專案,製作 Restfull API,可以讓客戶端訪問。
引用專案:PatrickLiu.MicroService.Interfaces
PatrickLiu.MicroService.Services
PatrickLiu.MicroService.Models
1)、Startup.cs 的程式碼
1 public class Startup 2 { 3 4 /// <summary> 5 /// 6 /// </summary> 7 /// <param name="services"></param> 8 public void ConfigureServices(IServiceCollection services) 9 { 10 services.AddControllers(); 11 services.AddSingleton<IUserService, UserService>(); 12 } 13 }
2)、Program.cs 的程式碼
1 public class Program 2 { 3 public static void Main(string[] args) 4 { 5 new ConfigurationBuilder() 6 .SetBasePath(Directory.GetCurrentDirectory()) 7 .AddCommandLine(args)//支援命令列 8 .Build(); 9 10 CreateHostBuilder(args).Build().Run(); 11 } 12 13 public static IHostBuilder CreateHostBuilder(string[] args) => 14 Host.CreateDefaultBuilder(args) 15 .ConfigureWebHostDefaults(webBuilder => 16 { 17 webBuilder.UseStartup<Startup>(); 18 }); 19 }
3)、UsersController.cs 的程式碼
1 /// <summary> 2 /// 使用者的 API 型別。 3 /// </summary> 4 [Route("api/[controller]")] 5 [ApiController] 6 public class UsersController : ControllerBase 7 { 8 #region 私有欄位 9 10 private readonly ILogger<UsersController> _logger; 11 private readonly IUserService _userService; 12 private IConfiguration _configuration; 13 14 #endregion 15 16 #region 建構函式 17 18 /// <summary> 19 /// 初始化該型別的新例項。 20 /// </summary> 21 /// <param name="logger">日誌記錄器。</param> 22 /// <param name="userService">使用者服務介面。</param> 23 /// <param name="configuration">配置服務。</param> 24 public UsersController(ILogger<UsersController> logger, IUserService userService, IConfiguration configuration) 25 { 26 _logger = logger; 27 _userService = userService; 28 _configuration = configuration; 29 } 30 31 #endregion 32 33 #region 例項方法 34 35 /// <summary> 36 /// 獲取一條記錄 37 /// </summary> 38 /// <param name="id"></param> 39 /// <returns></returns> 40 [HttpGet] 41 [Route("Get")] 42 public User Get(int id) 43 { 44 return _userService.FindUser(id); 45 } 46 47 /// <summary> 48 /// 獲取所有記錄。 49 /// </summary> 50 /// <returns></returns> 51 [HttpGet] 52 [Route("All")] 53 //[Authorize] 54 public IEnumerable<User> Get() 55 { 56 Console.WriteLine($"This is UsersController {this._configuration["port"]} Invoke"); 57 58 return this._userService.UserAll().Select((user => new User 59 { 60 ID = user.ID, 61 Name = user.Name, 62 Account = user.Account, 63 Password = user.Password, 64 Email = user.Email, 65 Role = $"{this._configuration["ip"]}:{this._configuration["port"]}", 66 LoginTime = user.LoginTime 67 })); ; 68 } 69 70 /// <summary> 71 /// 超時處理 72 /// </summary> 73 /// <returns></returns> 74 [HttpGet] 75 [Route("Timeout")] 76 public IEnumerable<User> Timeout() 77 { 78 Console.WriteLine($"This is Timeout Start"); 79 //超時設定。 80 Thread.Sleep(3000); 81 82 Console.WriteLine($"This is Timeout End"); 83 84 return this._userService.UserAll().Select((user => new User 85 { 86 ID = user.ID, 87 Name = user.Name, 88 Account = user.Account, 89 Password = user.Password, 90 Email = user.Email, 91 Role = $"{this._configuration["ip"]}:{this._configuration["port"]}", 92 LoginTime = user.LoginTime 93 })); ; 94 } 95 96 #endregion 97 }
2、編譯專案,啟動四個服務例項。
這四個服務例項是PatrickLiu.MicroService.ServiceInstance專案的例項,執行 dotnet 命令要在當前目錄下。
我的目錄:E:\Visual Studio 2019\Project\SourceCode\PatrickLiu.MicroService\PatrickLiu.MicroService.ServiceInstance\bin\Debug\netcoreapp3.1
(1)、dotnet PatrickLiu.MicroService.ServiceInstance.dll --urls="http://*:5726" --ip="127.0.0.1" --port=5726
可以訪問WebAPI地址,驗證是否成功。
地址:http://localhost:5726/api/users/all
效果如圖:
(2)、dotnet PatrickLiu.MicroService.ServiceInstance.dll --urls="http://*:5727" --ip="127.0.0.1" --port=5727
可以訪問WebAPI地址,驗證是否成功。
地址:http://localhost:5727/api/users/all
效果如圖:
(3)、dotnet PatrickLiu.MicroService.ServiceInstance.dll --urls="http://*:5728" --ip="127.0.0.1" --port=5728
可以訪問WebAPI地址,驗證是否成功。
地址:http://localhost:5728/api/users/all
效果如圖:
(4)、dotnet PatrickLiu.MicroService.ServiceInstance.dll --urls="http://*:5729" --ip="127.0.0.1" --port=5729
可以訪問WebAPI地址,驗證是否成功。
地址:http://localhost:5729/api/users/all
效果如圖:
3、下載NGINX 服務元件,預設下載 Windows 版本。
官網: http://nginx.org/en/download.html
4、部署NGINX伺服器。
將下載的檔案拷貝到沒有中文的目錄下,解壓檔案就可以。
我的存放目錄:D:\Programs\MicroServices
5、修改 NGINX.CONF 檔案。
修改該目錄D:\Programs\MicroServices\Nginx-1.18.0\conf 下的配置檔案。檔名:nginx.conf
增加的配置內容如下:
1 upstream MicroService{ 2 server localhost:5726; 3 server localhost:5727; 4 server localhost:5728; 5 server localhost:5729; 6 } 7 8 server { 9 listen 8080; 10 server_name localhost; 11 12 location / { 13 proxy_pass http://MicroService; 14 } 15 }
6、啟動 Nginx 伺服器。
注意:我是在Nginx當前目錄下邊。
Start nginx
NGINX埠預設:80,我改成了8080,沒有提示,一般會啟動正常。
可以訪問NGINX地址,驗證NGINX是否配置並且啟動成功。
地址:http://localhost:8080
效果如圖:
7、開啟瀏覽器,輸入地址:http://localhost:8080/api/users/all,多次重新整理頁面,你就會看到變化。我們已經實現了分散式、負載均衡。
如圖:5726 埠
如圖:5727埠
如圖:5728埠
如圖:5729埠
8、我們測試NGINX的高可用和可擴充套件性,得出以下結論。
(1)、Nginx 客戶端配置很簡單,直接訪問 Nginx 的閘道器地址就會路由到註冊服務例項。
(2)、如果服務例項掉線或者出現異常,可以自動察覺器狀況,下次輪訓可以跳過,不需人為參與。
(3)、如果系統增加了新的服務例項,Nginx 無法自動發現,需要人工修改配置檔案,然後重啟,才可以。
由於第三點的缺點,是我們這個版本的最大的缺點,我們不可能在龐大的系統中總是通過人力來做這些事。無法自動發現服務,我們需要繼續改進,那就是服務註冊發現中心。
三、 結束語
好了,今天就寫到這裡了,這個是介於分散式和微服務之間的一個很簡單的架構實現,雖然很簡單,但是我們所要表達的思想和所要獲取到的東西我們已經得到了。什麼東西都是由簡入繁的,下一期,繼續開始我們的有關微服務的進化吧。努力吧,每天進步一點
版权声明
本文为[itread01]所创,转载请带上原文链接,感谢
https://www.itread01.com/content/1604736304.html
边栏推荐
- Mobile pixel adaptation scheme
- python3操作gitlab
- VARCHART XGantt入门教程
- Application of UHF RFID medical blood management system
- 如何利用PopupWindow实现弹出菜单并解决焦点获取以及与软键盘冲突问题
- Empty test suite appears in JUnit test
- 心理咨询app开发所具备的优点与功能
- Win7 how to quickly type CMD and get to the required directory
- Composition of MRAM cache
- image operating system windows cannot be used on this platform
猜你喜欢
jenkins pipline stage 设置超时
Composition of MRAM cache
Empty test suite appears in JUnit test
Stm32f030f4p6 compatible with smart micro mm32f031f4p6
Shanghai Pudong Development Bank, which frequently receives penalty tickets, has been cheated by hundreds of millions of yuan in loans, and lacks of internal control?
失眠一个整晚上
September 3, 2020: naked writing algorithm: loop matrix traversal.
如何使用甘特图图层和筛选器
Top 5 Chinese cloud manufacturers in 2018: Alibaba cloud, Tencent cloud, AWS, telecom, Unicom
Yum [errno 256] no more mirrors to try solution
随机推荐
Application of UHF RFID medical blood management system
Git remote library rollback specified version
Stm32f030c6t6 compatible to replace mm32spin05pf
2020-08-15: under what circumstances should data tasks be optimized?
Characteristics of magnetic memory chip STT-MRAM
Shanghai Pudong Development Bank, which frequently receives penalty tickets, has been cheated by hundreds of millions of yuan in loans, and lacks of internal control?
Test the necessary skill points of siege lion! This article takes you to interpret the testing technology under Devops
September 9, 2020: naked writing algorithm: two threads print numbers 1-100 in turn.
August 14, 2020: what are the execution engines for data tasks?
How to create an interactive kernel density chart
In 2020, how can wechat seal numbers be quickly lifted?
Python 3 operates the Jenkins module API
A good thing for working people -- to temper the will of iron and steel requires such an efficient computer
Google browser realizes video playback acceleration function
关于DevOps的七大误解,99%的人都曾中过招!
k-vim安装及The ycmd server SHUT DOWN (restart with ':YcmRestartServer')这种错误的解决方法
小程序商城系统插件代码该如何写?怎么用代码检查添加插件是否成功?
WebAPI接口设计:SwaggerUI文档 / 统一响应格式 / 统一异常处理 / 统一权限验证
实验一
How to optimize the decoding performance of dynamsoft barcode reader