微服务模式下,实现前后端多资源服务调用
Micro
Services
首先,我先解釋下,文章標題的意思:
咋看起來特別像是一個標題黨????,可能是我沒想好怎么表達,其實白話文就是:在微服務場景下,肯定會有很多子服務API,那多個前端項目如何對接多個后端資源服務器項目呢?
也就是多個前端VUE如何對接多個后端的WebApi項目,這是問題,其實也不難,今天就簡單的討論討論,我這里列舉了三個場景的解決的方案,相信很多人都用過,都是比較主流的方案,文章的末端會有一個思考,就是如何實現第四種方案,這也就是我標題里為啥用微服務的原因了,本文主要是對微軟微服務框架eShop的思考。
既然了解了問題,那你不妨先思考一下,如果是你自己的項目出現了這樣的需求,VUE項目如何調用調用多個API項目,跟著我先慢慢往下看吧。
1、先來個需求吧
(圖片來源自Blog.Admin首頁)
相信如果留心的小伙伴,肯定這幾天看到了我的Admin后臺多了一個這樣的數據統計,特別是下邊的30天用戶注冊統計曲線圖,這里先說下這是干啥的:
大家都知道,現在我的所有在線項目都是基于IdentityServer4(下文簡稱Is4)作為統一認證平臺的,那這里的用戶信息肯定都是來自于Is4項目的,因為之前項目我一直在修改,用的是默認賬號,看不出來真實效果,所以我干脆去掉了默認賬號,讓每個訪問的用戶自己注冊(放心,基本填的數據基本都是假的,而且我也不會發郵件,其他人也看不到),我就時不時的需要登錄ids.neters.club認證平臺去看數據,時間長了就麻煩了,那么需求來了:如何集成到Admin后臺,通過線圖的形式展示呢,還能查看日志,用戶量,訪問情況,異常信息等?
但是Admin項目的后端Api是BlogCore的,我們已經習慣了這種一對一的開發模式,現在要實現一個前端對應多個后端的這種一對多的開發模式,那如何來處理呢。
其實我們簡單的思考一下就知道了,無論是一對一,還是一對多,甚至是多對多的情況,核心的問題,都是如何處理跨域的問題,如果瀏覽器不存在跨域的話,我們就可以任意的連接任何資源api了。當然除了跨域,第二個問題就是如何對資源的統一管理,這是個次要的重點知識。
當然,工欲善其事必先利其器,要實現這個需求,我們就首先需要在is4認證平臺里,添加對外的接口,這里是未加權的,以后我會說說在加權的情況下,如何來處理,其實是一樣的。
[HttpGet]public MessageModel<AccessApiDateView> GetAchieveUsers(){List<ApiDate>?apiDates?=?new?List<ApiDate>();var?users?=?_userManager.Users.Where(d?=>?!d.tdIsDelete).OrderByDescending(d?=>?d.Id).ToList();var tadayRegisterUser = users.Where(d => d.birth >= DateTime.Now.Date).Count();apiDates = (from n in usersgroup n by new { n.birth.Date } into gselect new ApiDate{date = g.Key?.Date.ToString("yyyy-MM-dd"),count = g.Count(),}).ToList();apiDates = apiDates.OrderByDescending(d => d.date).Take(30).ToList();if (apiDates.Count == 0){apiDates.Add(new ApiDate(){date = "沒數據,或未開啟相應接口服務",count = 0});}return new MessageModel<AccessApiDateView>(){msg = "獲取成功",success = true,response = new AccessApiDateView{columns = new string[] { "date", "count" },rows = apiDates.OrderBy(d => d.date).ToList(),today = tadayRegisterUser,}};}現在接口有了,前端頁面也設計好了(具體寫法就是vue-chart線圖,自行查看),那如何來解決調用問題呢,下邊就從四個方面來討論下。
2、萬物皆可代理模式
代理模式,可謂是軟件開發中,長盛不衰,一直活躍的東西,雖然有時候很多的名字是“代理”,而實際上上不是一回事,但是卻絲毫不影響我們來使用。
那我們在VUE開發中,也會用到代理模式,就是devProxy本地代理,代碼很簡單,基于node服務,只需要簡單的配置下,就可以將任意多個后端給代理到vue本地,只不過這里有個弊端,只能是本地開發模式下使用。
在項目根目錄下的vue.config.js中配置(沒有的話,新建即可)
devServer: {open: true, //配置自動啟動瀏覽器host: "127.0.0.1",port: 2364, // 當前vue項目 端口號https: false,hotOnly: false, // https:{type:Boolean}// proxy: null, // 設置代理//?proxy:?'http://123.206.33.109:8081',//?配置跨域處理,只有一個代理proxy: {// 配置多個代理"/api": {target:?"http://localhost:8081",//這里改成你自己的后端api端口地址,記得每次修改,都需要重新buildws: true,changeOrigin: true,pathRewrite: {// 支持路徑重寫,"^/api":?""?//?替換target中的請求地址}},"/images": {target: "http://localhost:8081",ws: true,changeOrigin: true},"/is4api": {target: "http://localhost:5004",ws: true,changeOrigin: true},},before: app => {}},是不是很簡單,這里我定義了三種策略方案,匹配了兩個后端項目,其中/is4api這個節點,就是針對is4項目的接口。
然后接口用相對路徑的方式來調用,設置baseUrl="",這樣就把所有的接口給代理到了前端了,這個很簡單,我就不截圖說明了。
上邊說了,這種方案是vue本地的代理,我們build后的靜態文件,是沒有這個功能的,畢竟沒有了node服務支持了,所以開發好項目上線的時候,就需要代理服務的反向代理功能了。我這里使用的是nginx做web服務器,那相應的配置如下:
這種就很簡單的實現了我們的需求,如果還有其他的微服務,我們就一一的增加進來,往里邊添加就行,總體來說還是很方便的。
但是從上邊看出來,我們本地開發的時候需要配置一套,然后項目上線的時候有需要配置一套,感覺不是很美觀,而且還對管理不友好。所以要是服務比較多的話,我們可以換另一種方案,就是網關。
3、微服務中網關作用很大
(微服務簡易網關,圖源網絡)
上邊咱們說到了代理模式,在比較簡單的,或者說服務比較少的情況下,還是一種比較常見、比較高效的開發方案,但是隨著我們的項目的服務增多,因為我這里只有用戶數據和博客數據,分別對應的是Blog.Idp項目和Blog.Core項目,那如果以后需要新增其他功能的時候,如上圖,就需要一個統一的平臺或者功能來管理我們的所有資源api了,網關就是一個很不錯的選擇,而且也可以結合其他的功能組件,中間件等擴展,比如服務注冊和治理,熔斷,負載等等。
既然說到了網關,那常見的網關就是Ocelot、Zuul、Kong這些,其中優劣不予置評,我習慣用Ocelot,那今天就說它。
第一:創建一個網關項目。
我其實blog.core項目中已經有了,你可以查看下Blog.Core.AdminMvc項目,這里什么都沒有,我就用來做網關了,引用Ocelot組件
<PackageReference Include="Ocelot" Version="16.0.1" />第二:配置Ocelot服務
在startup.cs文件中,配置服務和中間件
第三:配置網關策略
在根目錄下,創建OcelotGatewaySet.json文件,然后添加內容,具體的邏輯,自行百度查看把,很簡單,就是通過一定的配置,把分散的下游項目,也就是分散的微服務項目,給交給一個統一的上游地址,只不過有一定的url規則。
{"Routes": [{"DownstreamPathTemplate": "/api/{url}","DownstreamScheme": "http","DownstreamHostAndPorts": [{"Host": "localhost","Port": 8081}],"UpstreamPathTemplate": "/gateway/api/{url}","UpstreamHttpMethod": ["Get","Post","Put","Delete"],"LoadBalancerOptions": {"Type": "RoundRobin"}},{"DownstreamPathTemplate": "/is4api/{url}","DownstreamScheme": "http","DownstreamHostAndPorts": [{"Host": "localhost","Port": 5004}],"UpstreamPathTemplate": "/gateway/is4api/{url}","UpstreamHttpMethod": ["Get","Post","Put","Delete"],"LoadBalancerOptions": {"Type": "RoundRobin"}}],"GlobalConfiguration": {"BaseUrl": "http://localhost:9000"} }這里我定義了兩個下游,就是blogcore的8081,is4的5004,然后分別對應了上游的9000項目的兩個地址:"/gateway/api/{url}"、"/gateway/is4api/{url}"。
第四步:添加Json文件到應用
上邊我們自定義了配置策略文件,肯定是需要添加到應用里的,不然不會被識別,除非你是直接寫到了appsettings.json里,但是這樣好像又不太好,還是單獨寫一個文件吧:
public static IHostBuilder CreateHostBuilder(string[] args) =>Host.CreateDefaultBuilder(args)// 配置json文件.ConfigureAppConfiguration((hostingContext, config) =>{config.AddJsonFile("OcelotGatewaySet.json");}).ConfigureWebHostDefaults(webBuilder =>{webBuilder.UseStartup<Startup>().UseUrls("http://*:9000");});然后就可以看到效果了
這樣,以后無論多少個下游微服務,都可以集中到網關里,那前端vue項目,就很簡單的配置一個9000就行了。
這樣不僅可以實現多對多連接,還可以方便服務管理,是不是很方便。但是也有一個小問題,就是不好做服務之間的業務處理,比如我要在blogcore某個業務中,使用is4的用戶數據,也就是跨項目跨數據庫實現業務邏輯和事務,該怎么辦呢,別著急,我項目中已經集成了多庫操作,來看看吧。
4、扔到后端:多庫模式
BlogCore目前支持,單庫-多庫-讀寫分離三種模式,事務當然也是支持,不過跨服跨庫事務,可能需要分布式事務的組件來實現。
具體的內容可以參考《【項目升級】單庫、多庫、讀寫分離 · 任你選》
具體的寫法呢,我的b站視頻里也錄制了,都是很簡單的操作,只需要簡單的配置,就可以實現多庫處理,然后倉儲層連接好后,還可以配合著service層來增刪改查,就比如這樣的來寫。
第一:當然是配置連接字符串
在appsettings.json文件中,做多庫處理,如果不會,可以看我的視頻
https://www.bilibili.com/video/BV1BJ411B7mn?p=6
第二:定義對應的Model實體,在SugarTable特性里,配置好數據庫的ConnId,這個配置的信息在appsettings.json里。
namespace Blog.Core.Model.IDS4DbModels {/// <summary>/// 以下model 來自ids4項目,多庫模式,為了調取ids4數據/// 用戶表/// </summary>[SugarTable("AspNetUsers", "WMBLOG_MYSQL_2")]public class ApplicationUser{public string LoginName { get; set; }public string RealName { get; set; }public int sex { get; set; } = 0;public int age { get; set; }public DateTime birth { get; set; } = DateTime.Now;public string addr { get; set; }public bool tdIsDelete { get; set; }} }第三:就是直接創建Service層,當然,如果你有封裝單獨的邏輯業務,可以自己創建一個倉儲層,但是如果普通的CURD,可以直接使用泛型基類倉儲接口:
public class ApplicationUserServices : BaseServices<ApplicationUser>, IApplicationUserServices{IBaseRepository<ApplicationUser> _dal;public ApplicationUserServices(IBaseRepository<ApplicationUser> dal){this._dal = dal;base.BaseDal = dal;}}這樣就可以輕松的實現連接了。可以在控制器,甚至是Service里寫邏輯了,這里就不多介紹了。
但是!其實這種寫法呢,應該不符合今天內容的主旨,這么寫雖然可以任意的再后端做多庫處理,寫業務了,但是如果微服務多了怎么辦,又不好做控制,負載什么的。而且又不那么靈活,甚至如果一個服務崩了,也會導致主服務受到影響。
那為什么我還要拿出來說一下呢,主要是想引出第四種方案,就是微服務下,在使用網關、做服務治理、負載均衡的情況下,如何實現多服務之間的調用。
5、如果有第四種方案?
這里先說下第四種思路的由來:
就是上邊提到的問題,在微服務場景下,我們是講一個個服務都拆開限界的,各個子服務獨立做負載均衡,服務注冊和治理,然后通過網關,將所有的服務連接起來,看著沒問題,但是如果某兩個,或者多個子服務之間相互左右,或者相互調用來實現交叉業務邏輯的時候,是不是感覺很蒼白無力,從而導致了很多人問了這樣的問題:
微服務好是好,但是我想多表聯查怎么辦?看似和微服務,和DDD背道而馳,但是卻是不得不考慮的一個問題。
當然,方案還是有的,比如常見的RestFul、gRPC、MQ、Bus等等技術,這些知識點,其實就是第四種方案,其實就是第二和第三種方案的結合體。
這些內容在微軟的微服務框架eShopOnContainer都可以看的到,我也正在學習和講解,想了解的時候,可以看一看:
《#微服務之eShop講解》
END
歡迎將文章分享到朋友圈
如需轉載,請在后臺回復“轉載”獲取授權
▼
更多精彩推薦,老張的哲學
▼
把時間交給閱讀
總結
以上是生活随笔為你收集整理的微服务模式下,实现前后端多资源服务调用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BeetleX之HTTP网关部署
- 下一篇: [C#.NET 拾遗补漏]09:数据标注