ASP.NET Core微服务之基于Ocelot实现API网关服务(1)
Tip: 此篇已加入.NET Core微服务基础系列文章索引
一、啥是API网关?
API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口。这样就可以明显的简化客户端实现和微服务应用程序之间的沟通方式。以前的话,客户端不得不去请求微服务A(假设为Customers),然后再到微服务B(假设为Orders),然后是微服务C(假设为Invoices)。客户端需要去知道怎么去一起来消费这三个不同的service。使用API网关,我们可以抽象所有这些复杂性,并创建客户端们可以使用的优化后的端点,并向那些模块们发出请求。API网关的核心要点是:所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能(比如验证、鉴权、监控等等)。
微服务架构中的任何一个环节,都是可以说很久的,而我没有太多经验,也就不多谈了。
二、开源项目:Ocelot
Ocelot是一个使用.NET Core平台上的一个API Gateway,这个项目的目标是在.NET上面运行微服务架构。Ocelot框架内部集成了IdentityServer(身份验证)和Consul(服务注册发现),还引入了Polly(上一篇博文中提到过)来处理进行故障处理。
Ocelot github : https://github.com/TomPallister/Ocelot
三、快速开始第一个API网关
3.1 安装Ocelot
NuGet>Install-Package Ocelot
3.2 快速准备两个API服务
(1)准备一个ClientService
创建一个ASP.NET Core WebAPI程序,保留默认ValuesController,做一下修改:
[Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet] public IEnumerable<string> Get() { return new string[] { "ClinetService-value1", "ClinetService-value2" }; } ...... }
(2)准备一个ProductService
创建一个ASP.NET Core WebAPI程序,保留默认ValuesController,做一下修改:
[Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet] public IEnumerable<string> Get() { return new string[] { "ProductService-value1", "ProductService-value2" }; } ...... }
3.3 静态配置两个API服务
创建一个ASP.NET Core WebAPI程序,这里命名为APIGateway.
(1)新建一个json文件:eg.configuration.json
首先,一个最基本的配置文件如下:
{ "ReRoutes": [], "GlobalConfiguration": { "BaseUrl": "https://api.mybusiness.com" } }
这里特别注意一下BaseUrl是我们外部暴露的Url,比如我们的Ocelot运行在http://123.111.11.1的一个地址上,但是前面有一个Nginx绑定了域名http://api.edisonchou.cn,那这里我们的BaseUrl就是 http://api.edisonchou.cn。现在我们的实验环境不存在这个条件,所以我们暂时不需要配置这个option。下面我们根据模板将刚刚创建并启动的两个Service的信息进行了配置:
{ "ReRoutes": [ // API:CAS.ClientService { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "192.168.2.231", "Port": "8810" } ], "UpstreamPathTemplate": "/ClientService/{url}", "UpstreamHttpMethod": [ "Get", "Post" ] }, // API:CAS.ProductService { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "DownstreamHostAndPorts": [ { "Host": "192.168.2.231", "Port": "8820" } ], "UpstreamPathTemplate": "/ProductService/{url}", "UpstreamHttpMethod": [ "Get", "Post" ] } ] }
其中,我们得了解一下微服务架构中的上游服务器和下游服务器,一般下游服务器指的是提供API服务的REST Service Server(比如WebAPI、WCF App等),而上游服务器则指的是提供Web网页服务的Web Server(比如MVC Application,可能需要访问REST Service)。那么,这里我们可以了解到:
- Downstream 是下游服务配置 => 即我们刚刚创建的提供API服务的配置,我们会指定PathTemplate,Host和Port等信息(具体调哪一台服务器是由我说了算)
- UpStream 是上游服务配置 => 即服务消费方(eg.MVC Server, SPA App)的调用配置(你要怎么按照什么URL格式和什么HTTP类型调用我才能理解)
通过配置文件,我们可以猜测Ocelot的实现原理大致应该就是把客户端对网关的请求(Request),按照configuration.json的映射配置,转发给对应的后端http service,然后从后端http service获取响应(Response)后,再返回给客户端。当然,具体细节应该十分复杂,等后面有时间深入看看实现机制。
其他不再解释,可以看明白,另外,需要对这个配置文件进行以下设置:为了确保直接运行时能够找到这个configuration.json文件
*._通过配置文件可以完成对Ocelot的功能配置:路由、服务聚合、服务发现、认证、鉴权、限流、熔断、缓存、Header头传递等。在配置文件中包含两个根节点:ReRoutes和GlobalConfiguration。ReRoutes是一个数组,其中的每一个元素代表了一个路由,我们可以针对每一个路由进行以上功能配置。_
(2)改写Program和StartUp类,才能正常使用Ocelot
①在Program类的BuildWebHost中让程序读取configuration.json文件
public class Program { public static void Main(string[] args) { BuildWebHost(args).Run(); } public static IWebHost BuildWebHost(string[] args) { return WebHost.CreateDefaultBuilder(args) .UseStartup<Startup>() .UseUrls($"http://{IP}:{Port}") .ConfigureAppConfiguration((hostingContext, builder) => { builder.AddJsonFile("configuration.json", false, true); }) .Build(); } }
②在StartUp类中为Ocelot注入配置,并启动Ocelot
public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { //services.AddMvc(); -- no need MVC // Ocelot services.AddOcelot(Configuration); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } //app.UseMvc(); -- no need MVC // Ocelot app.UseOcelot().Wait(); } }
3.3 测试一下
(1)先启动ClientService和ProductService => 也可以通过在VS中更改启动顺序来指定
(2)再启动APIGateway,在浏览器中直接访问API网关所在的地址和端口(这里是192.168.2.231:8800)进行测试:先请求ClientService,再请求ProductService,可以看到API网关对请求进行了转发,服务消费方不需要记住每个service所在的IP和端口,而是只需要告诉网关我需要消费哪个service即可。
*._tip:_这里配置的PathTemplate大小写不敏感,可以选择通过设置ReRouteIsCaseSensitive:true来实现大小写敏感
到这里,第一个API网关的实现就结束了,但是对于众多的微服务,如果我们都一一硬编码地配置其IP和Port在配置文件中,不适合微服务架构的风格,因为众多的服务地址变化会让静态配置的工作变得越来越大。因此,我们学习了服务发现,那么是否可以结合服务发现呢?Ocelot + Consul的方式为我们给出了答案。
四、Ocelot+Consul的结合
4.1 实验节点部署结构
这里仍然采用之前的Consul实验集群,三个Consul Server节点(1个leader,2个follwer),一个Consul Client节点(部署了两个服务ClientService和ProductService),以及一个API网关节点(基于Ocelot)。
4.2 启动Consul
启动方式以及步骤这里不再赘述,如不了解请浏览我的前两篇博文《.NET Core微服务之基于Consul实现服务治理》以及《.NET Core微服务之基于Consul实现服务治理(续)》。这里可以看到,我们已经成功地注册了ClientService和ProductService。
4.3 启动API Gateway
(1)为了适配Consul服务发现,减少服务IP和Port的hard-code,我们需要改一下配置文件:
{ "ReRoutes": [ // API01:CAS.ClientService { "UseServiceDiscovery": true, // use Consul service discovery "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "ServiceName": "CAS.ClientService", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UpstreamPathTemplate": "/api/clientservice/{url}", "UpstreamHttpMethod": [ "Get", "Post" ], "ReRoutesCaseSensitive": false // non case sensitive }, // API02:CAS.ProductService { "UseServiceDiscovery": true, // use Consul service discovery "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "ServiceName": "CAS.ProductService", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UpstreamPathTemplate": "/api/productservice/{url}", "UpstreamHttpMethod": [ "Get", "Post" ], "ReRoutesCaseSensitive": false // non case sensitive } ], "GlobalConfiguration": { //"BaseUrl": "https://api.mybusiness.com" "ServiceDiscoveryProvider": { "Host": "192.168.80.100", // Consul Service IP "Port": 8500 // Consul Service Port } } }
Ocelot提供了基本的负载均衡选项(LoadBalanceOptions):轮询和最小连接数,如果我们部署了多个一样的服务,那么我们设置一个选项。
(2)其他代码无须更改,对于基本用法,我们要做的基本只是对配置文件的修改。配置完成后,即可启动API网关项目。
4.4 测试
(1)请求ClientService
(2)请求ProductService
五、小结
本篇介绍了API网关的基础概念以及一个基于适合于.NET Core的开源项目Ocelot,并通过两个小案例(一个静态配置服务,一个结合Consul服务发现)来了解了API网关的作用和Ocelot的最基础的用法。下一篇会继续Ocelot的一些比较有用的功能(比如:限流、熔断、缓存,以及结合Swagger),继续做一些实践,也希望到时可以总结下来与各位园友分享。
示例代码
Click here => 点我下载
参考资料
杨晓东,《谈谈微服务中的API网关》
桂素伟,《Ocelot + Consul实践》
杨中科,《.NET微服务直播课课件pdf》
李朝强,《ASP.NET Core API网关Ocelot》
jesse 腾飞,《.NET Core开源API网关 – Ocelot中文文档》
Ocelot官网:https://github.com/ThreeMammals/Ocelot => _tip:_ 张善友大队长为主要贡献者之一
Ocelot官方文档:http://ocelot.readthedocs.io/en/latest/index.html
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
ASP.NET Core微服务之基于Polly+AspectCore实现熔断与降级机制
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一、熔断、降级与AOP 1.1 啥是熔断? 在广义的解释中,熔断主要是指为控制股票、期货或其他金融衍生产品的交易风险,为其单日价格波动幅度规定区间限制,一旦成交价触及区间上下限,交易则自动中断一段时间(“熔即断”),或就此“躺平”而不得超过上限或下限(“熔而不断”)。 而对于微服务来说,熔断就是我们常说的“保险丝”,意为当服务出现某些状况时,切断服务,从而防止应用程序不断地常识执行可能会失败的操作造成系统的“雪崩”,或者大量的超时等待导致系统卡死等情况,很多地方也将其成为“过载保护”。 1.2 啥是降级? 降级的目的就是当某个服务提供者发生故障的时候,向调用方返回一个_替代响应或者错误响应_。 例如:假设有一个短信服务,其调用联通接口服务器发送短信服务(假设这里调用联通接口最方便,最省事也最经济)失败之后,会尝试改用移动短信服务器(假设这里调用移动服务器比较不方便也不经济)发送,如果移动服务器调用也失败,那么还会尝试改用电信短信服务器(假设这里调用电信服务器最不省事和最不经济),如果还失败,则返回“失败”响应; 降级的另一个...
- 下一篇
ASP.NET Core微服务之基于Ocelot实现API网关服务(2)
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一、负载均衡与请求缓存 1.1 负载均衡 为了验证负载均衡,这里我们配置了两个Consul Client节点,其中ClientService分别部署于这两个节点内(192.168.80.70与192.168.80.71)。 为了更好的展示API Repsonse来自哪个节点,我们更改一下返回值: [Route("api/[controller]")] public class ValuesController : Controller { // GET api/values [HttpGet] public IEnumerable<string> Get() { return new string[] { $"ClinetService: {DateTime.Now.ToString()} {Environment.MachineName} " + $"OS: {Environment.OSVersion.VersionString}" }; } ...... } Ocelot的配置文件中确保有负载均衡的设置: ...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS关闭SELinux安全模块
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Hadoop3单机部署,实现最简伪集群