首先恭喜你,进入微服务的开发世界。微服务属于架构演进中的一种阶段,其特色是根据业务模块水平划分服务种类,每一个服务能够独立部署并互相隔离,并对外提供轻量的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网关!