首先恭喜你,進入微服務的開發世界。微服務屬於架構演進中的一種階段,其特色是根據業務模塊水平劃分服務種類,每一個服務能夠獨立部署並互相隔離,並對外提供輕量的Api調用,服務具備高可用特性。css
微服務應遵循的設計原則:nginx
我從2017年12月開始接觸微服務概念,並開始着手構建公司的微服務平臺,系統架構採用 .net core webapi方式組織,隨着微服務的增多,愈來愈須要一個統一入口管理這些微服務。git
Nginx是由IgorSysoev爲俄羅斯訪問量第二的Rambler.ru站點開發的,一個高性能的HTTP和反向代理服務器。2012年,Nginx榮獲年度雲計算開發獎,併成長爲世界第二大Web服務器。全世界流量最高的前1000名網站中,超過25%都使用Nginx來處理海量的互聯網請求。github
Nginx很牛掰,業界公認的首選,選擇它做爲api網關,能夠說不用開發介入,只須要運維的同窗好好規劃配置便可。
web
網關配置規劃以下:
/api/ServiceA —> ServiceA
/api/ServiceB —> ServiceB
/api/ServiceC —> ServiceC
外部統一的訪問入口是Nginx,而後根據服務名稱路由到不一樣的微服務站點。
api網關的路由難題解決了,其餘熔斷,灰度發佈,線上測試,日誌攔截等功能nginx作起來相對比較吃力,不過對於中小型平臺已經夠用了。json
半年後,換了家公司,公司微服務平臺搭建採用Thrift RPC做爲各個微服務的通信協議,因爲當時的無知(Socket協議已被Nginx支持),因此決定寫個Api代理類,沒敢叫Api網關,是由於實現的功能僅限於路由!
僅僅是路由,固然是祭出 .net core Web應用。api
MVC框架包就別包含了,輕量的性能才能好!
Main函數初始化線程池大小跨域
//初始化線程池最小大小 爲 300 ThreadPool.GetMinThreads(out var wt, out var ct); if (wt < 300 || ct < 300) { ThreadPool.SetMinThreads(Math.Max(wt, 300), Math.Max(ct, 300)); }
**注意:**線程池不是越大越好,最佳選擇約等於 cpu內核的2倍,有個公式參考:
多說一句吧,思考下:服務器
爲何Nginx只用4個線程發揮出的性能就大大超越了100個進程的Apache HTTPD?回想一下計算機科學的基礎知識,答案實際上是很明顯的。markdown
我要支持跨域訪問:
public void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddPolicy("AllowAll", p => p.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials()); }); }
配置下使用中間件
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseCors("AllowAll"); app.UseMiddleware<ProxyMiddleware>(); // app.UseMvc(); }
路由轉發,一箇中間件便可搞定。
public class ProxyMiddleware { private readonly RequestDelegate m_Next; public ProxyMiddleware(RequestDelegate next) { this.m_Next = next; } public Task Invoke(HttpContext context) { if (context.Request.Method?.ToUpper() == "GET") { var path = context.Request.Path.HasValue ? context.Request.Path.ToString().ToLower() : string.Empty; if (string.IsNullOrEmpty(path) || path.Equals("/") || path.Equals("/api") || path.Equals("/api/")) { return this.SendConstRespond(context); } //增長一個代理網關接口,返回微服務列表 else if (path.EndsWith("/getallservices")) { return this.SendServiceListRespond(context); } return this.SendStringRespond(context); } if (context.Request.ContentType == null || context.Request.ContentType.IndexOf("application/json") < 0) { context.Response.StatusCode = 403; context.Response.ContentType += "application/json;charset=utf-8;"; return context.Response.WriteAsync("Please set ContentType=application/json"); } return this.SendStringRespond(context); } private Task SendStringRespond(HttpContext context) { context.Response.StatusCode = 200; context.Response.ContentType += "application/json;charset=utf-8;"; Task task = new Task(() => { if (ServerSetting.Config.QuantumConfig.RpcService.ServerType==ServerType.HttpWebApi) { string constResp = QuantumHttpProxy.SendHttp(context); using (var strStream = new StreamWriter(context.Response.Body)) { strStream.Write(constResp); strStream.Flush(); } } else { QuantumHttpProxy.Send(context); } }); task.Start(); return task; } private Task SendConstRespond(HttpContext context) { context.Response.StatusCode = 200; context.Response.ContentType += "application/json;charset=utf-8;"; Task task = new Task(() => { var constResp = new { rid = string.Empty, c = 200, msg = "Access api gateway success!" }; using (var strStream = new StreamWriter(context.Response.Body)) { strStream.Write(JsonConvert.SerializeObject(constResp)); strStream.Flush(); } }); task.Start(); return task; } private Task SendServiceListRespond(HttpContext context) { context.Response.StatusCode = 200; context.Response.ContentType += "application/json;charset=utf-8;"; Task task = new Task(() => { var svrs = ServerSetting.Config?.HttpProxy?.Items?.Select(x => x.Name)?.ToList() ?? new List<string>(); var constResp = new { rid = Guid.NewGuid().ToString("N"), c = 200, v = svrs, }; using (var strStream = new StreamWriter(context.Response.Body)) { strStream.Write(JsonConvert.SerializeObject(constResp)); strStream.Flush(); } }); task.Start(); return task; } }
上面的代碼裏 有 QuantumHttpProxy,是咱們封裝的rpc調用,所以各位同窗要用此類,請自行修改之。
沒有重試,熔斷也沒有降級,是否很low?
這就是實際實踐的力量,沒必要耗費太多精力在一些非關鍵點上!
好吧,我認可我研究了 **polly**類庫,重試,熔斷,降級都準備好了,你就起航吧~~~
另外:造輪子只適合特定場景,小投入就能夠完成的某些特定功能,好比上面的路由功能!若是你是雲服務,能夠重點考慮下 阿里API網關,亞馬遜api網關!