net core体系-API-1Ocelot-(3)简单项目实战
首先,让我们简单了解下什么是API网关?
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
其次,我们了解下Ocelot框架
Ocelot的目标是使用.NET运行微服务/面向服务架构,我们需要一个统一的入口进入我们的服务,提供监控、鉴权、负载均衡等机制,也可以通过编写中间件的形式,来扩展Ocelot的功能。 Ocelot是一堆特定顺序的中间件。
Ocelot框架内部集成了IdentityServer和Consul(服务注册发现),还引入了Polly来处理进行故障处理,关于Polly,可以在这篇博客中了解更多《已被.NET基金会认可的弹性和瞬态故障处理库Polly介绍》
Ocelot开源地址:https://github.com/TomPallister/Ocelot
接下来,我们就针对Ocelot的具体用法展开介绍。
这里使用的Ocelot版本为2.0,.Net Core版本2.0
1、搭建Asp.net Core WebApi项目,引用Ocelot.dll。
Nuget控制台,执行Ocelot安装。
1
|
PM>Install-Package Ocelot |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
GET https: //api .nuget.org /v3/registration3-gz-semver2/ocelot/index .json OK https: //api .nuget.org /v3/registration3-gz-semver2/ocelot/index .json 104 毫秒 GET https: //api .nuget.org /v3/registration3-gz-semver2/ocelot/page/1 .5.0-unstable0134 /2 .0.0.json OK https: //api .nuget.org /v3/registration3-gz-semver2/ocelot/page/1 .5.0-unstable0134 /2 .0.0.json 108 毫秒 正在还原 J:\Demo\RichCodeBox\APIGatewayApp\APIGatewayApp.csproj 的包... GET https: //api .nuget.org /v3-flatcontainer/ocelot/index .json OK https: //api .nuget.org /v3-flatcontainer/ocelot/index .json 476 毫秒 GET https: //api .nuget.org /v3-flatcontainer/ocelot/2 .0.0 /ocelot .2.0.0.nupkg OK https: //api .nuget.org /v3-flatcontainer/ocelot/2 .0.0 /ocelot .2.0.0.nupkg 125 毫秒 GET https: //api .nuget.org /v3-flatcontainer/identityserver4 .accesstokenvalidation /index .json GET https: //api .nuget.org /v3-flatcontainer/cachemanager .core /index .json GET https: //api .nuget.org /v3-flatcontainer/cachemanager .microsoft.extensions.configuration /index .json GET https: //api .nuget.org /v3-flatcontainer/cachemanager .microsoft.extensions.logging /index .json GET https: //api .nuget.org /v3-flatcontainer/consul/index .json GET https: //api .nuget.org /v3-flatcontainer/polly/index .json GET https: //api .nuget.org /v3-flatcontainer/identityserver4/index .json OK https: //api .nuget.org /v3-flatcontainer/identityserver4 .accesstokenvalidation /index .json 133 毫秒 GET https: //api .nuget.org /v3-flatcontainer/identityserver4 .accesstokenvalidation /2 .1.0 /identityserver4 .accesstokenvalidation.2.1.0.nupkg OK https: //api .nuget.org /v3-flatcontainer/cachemanager .microsoft.extensions.logging /index .json 286 毫秒 OK https: //api .nuget.org /v3-flatcontainer/polly/index .json 287 毫秒 OK https: //api .nuget.org /v3-flatcontainer/identityserver4 .accesstokenvalidation /2 .1.0 /identityserver4 .accesstokenvalidation.2.1.0.nupkg 160 毫秒 GET https: //api .nuget.org /v3-flatcontainer/cachemanager .microsoft.extensions.logging /1 .1.1 /cachemanager .microsoft.extensions.logging.1.1.1.nupkg |
2、修改Startup程序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
/// <summary> /// /// </summary> /// <param name="environment"></param> public Startup(IHostingEnvironment environment) { var builder = new Microsoft.Extensions.Configuration.ConfigurationBuilder(); builder.SetBasePath(environment.ContentRootPath) .AddJsonFile( "appsettings.json" , false , reloadOnChange: true ) .AddJsonFile($ "appsettings.{environment.EnvironmentName}.json" , optional: false , reloadOnChange: true ) .AddJsonFile( "configuration.json" , optional: false , reloadOnChange: true ) .AddEnvironmentVariables(); Configuration = builder.Build(); } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
/// <summary> ///modified:配置 /// </summary> public IConfigurationRoot Configuration { get ; } /// <summary> /// 配置服务 /// </summary> /// <param name="services"></param> public void ConfigureServices(IServiceCollection services) { Action<ConfigurationBuilderCachePart> settings = (x) => { x.WithMicrosoftLogging(log => { log.AddConsole(LogLevel.Debug); }).WithDictionaryHandle(); }; services.AddOcelot(Configuration, settings); //services.AddMvc(); } /// <summary> /// 配置Ocelot /// </summary> /// <param name="app"></param> /// <param name="env"></param> public async void Configure(IApplicationBuilder app, IHostingEnvironment env) { //if (env.IsDevelopment()) //{ // app.UseDeveloperExceptionPage(); //} await app.UseOcelot(); //app.UseMvc(); } /// <summary> /// 入口程序 /// </summary> /// <param name="args"></param> public static void Main( string [] args) { IWebHostBuilder builder = new WebHostBuilder(); builder.ConfigureServices(s => { s.AddSingleton(builder); }); builder.UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .UseApplicationInsights(); var host = builder.Build(); host.Run(); } |
3、配置Ocelot。
我们新建一个名为configuration的json文件,配置如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
{ "ReRoutes" : [ { "DownstreamPathTemplate" : "/api/values" , "DownstreamScheme" : "http" , "DownstreamHost" : "localhost" , "DownstreamPort" : 8801, "UpstreamPathTemplate" : "/api/values" , "UpstreamHttpMethod" : [ "Get" ], "QoSOptions" : { "ExceptionsAllowedBeforeBreaking" : 3, "DurationOfBreak" : 10, "TimeoutValue" : 5000 }, "HttpHandlerOptions" : { "AllowAutoRedirect" : false , "UseCookieContainer" : false }, "AuthenticationOptions" : { } }, { "DownstreamPathTemplate" : "/api/product" , "DownstreamScheme" : "http" , "DownstreamPort" : 8802, "DownstreamHost" : "localhost" , "UpstreamPathTemplate" : "/api/product" , "UpstreamHttpMethod" : [ "Get" ], "QoSOptions" : { "ExceptionsAllowedBeforeBreaking" : 3, "DurationOfBreak" : 10, "TimeoutValue" : 5000 }, "AuthenticationOptions" : { } } ], "GlobalConfiguration" : { "RequestIdKey" : "OcRequestId" , "AdministrationPath" : "/admin" } } |
在这里,我们配置了两个服务,端口分别为8801和8802的。
Ocelot支持负载均衡(提供轮询、最少访问)。Ocelot大部分功能,都可以通过中间件来完成,也可以实现和重写中间件。
Ocelot原理非常简单,这里的配置文件,体现了上游请求和下游服务间的映射关系,你可以理解为,上游是客户端直接调用的URL ,下游,则是对应我们开发的服务。
4、新增两个WebApi项目,分别为APIUserServiec和APIProductService。
API服务 | 端口(Port) |
APIUserServiec | 8801 |
APIProductService | 8802 |
解决方案如下:
5、配置VS启动端口:
依次类推,分别设置端口。
6、启动项目。
配置多个项目启动。
F5启动项目。
再通过API网关,访问商品服务:http://localhost:5000/api/product。
常见问题:
首次在启动API网关时,触发以下错误。
Sequence contains no matching element
根据错误详细信息,可知原因是由于系统调用AddIdentityServer方法时,触发异常。
刚开始,怀疑是配置文件configuration.json文件配置导致的,Ocelot2.0版,采用官方配置仍然触发该异常,由此排除这种可能。接下来,直接从github上克隆源代码,查看。
找到触发错误的地方,

private static void AddIdentityServer(this IServiceCollection services, IIdentityServerConfiguration identityServerConfiguration, IConfigurationRoot configurationRoot)
{
services.TryAddSingleton<IIdentityServerConfiguration>(identityServerConfiguration);
services.TryAddSingleton<IHashMatcher, HashMatcher>();
var identityServerBuilder = services
.AddIdentityServer(o => {
o.IssuerUri = "Ocelot";
})
.AddInMemoryApiResources(Resources(identityServerConfiguration))
.AddInMemoryClients(Client(identityServerConfiguration))
.AddResourceOwnerValidator<OcelotResourceOwnerPasswordValidator>(); //todo - refactor a method so we know why this is happening
var whb = services.First(x => x.ServiceType == typeof(IWebHostBuilder));//这个地方触发了错误
var urlFinder = new BaseUrlFinder((IWebHostBuilder)whb.ImplementationInstance);
var baseSchemeUrlAndPort = urlFinder.Find();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear(); services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(o =>
{
var adminPath = configurationRoot.GetValue("GlobalConfiguration:AdministrationPath", string.Empty);
o.Authority = baseSchemeUrlAndPort + adminPath;
o.ApiName = identityServerConfiguration.ApiName;
o.RequireHttpsMetadata = identityServerConfiguration.RequireHttps;
o.SupportedTokens = SupportedTokens.Both;
o.ApiSecret = identityServerConfiguration.ApiSecret;
}); //todo - refactor naming..
if (string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificateLocation) || string.IsNullOrEmpty(identityServerConfiguration.CredentialsSigningCertificatePassword))
{
identityServerBuilder.AddDeveloperSigningCredential();
}
else
{
//todo - refactor so calls method?
var cert = new X509Certificate2(identityServerConfiguration.CredentialsSigningCertificateLocation, identityServerConfiguration.CredentialsSigningCertificatePassword);
identityServerBuilder.AddSigningCredential(cert);
}

var whb = services.First(x => x.ServiceType == typeof(IWebHostBuilder));
这就代码触发了错误,是由于表达式条件不成立,导致First发生异常,这就简单了,我们修改Main函数,
把这句代码:
var builder = new WebHostBuilder();
改成:
IWebHostBuilder builder = new WebHostBuilder();
这样,就解决了问题,API网关启动成功。另外,官方例子https://github.com/TomPallister/Ocelot/blob/develop/test/Ocelot.ManualTest/Program.cs中,写法是正确的,大家自己写的时候,注意把IWebHostBuilder换成var会引发错误。
这样,使用Ocelot框架搭建API网关的工作已经完成,尝试通过访问API网关,来访问下游的服务。
此实例源码:https://gitee.com/lichaoqiang/RichCodeBox.git
欢迎大家一起研究探讨,开启你的微服务之路。
net core体系-API-1Ocelot-(3)简单项目实战的更多相关文章
- ASP.NET Core 系列视频完结,新项目实战课程发布。
今天把MVC的章节完成了,给大家从头到尾做了一个登录注册的示例,带前后端Model验证,算是完整的示例.同时借助于eShopOnContainers的示例也做了一个DBContextSeed的包装器来 ...
- net core体系-web应用程序-2项目简单案例
阅读目录 NO1 留言板(mysql的使用) NO2 聊天室(WebSocket的使用) NO3 找工作(AngleSharp的使用) 部署多个站点 一些其它的细节 部署阿里云 mysql的客户端 ...
- net core体系-web应用程序-3项目结构、配置文件详解
一.应用程序文件结构 如下图所示,相比于Asp.Net项目,在新建的Asp.Net Core项目中,没有了Global.asax以及Web.config这样的文件,但多了几个其他主要的文件,它们分别为 ...
- Spark RDD/Core 编程 API入门系列 之rdd实战(rdd基本操作实战及transformation和action流程图)(源码)(三)
本博文的主要内容是: 1.rdd基本操作实战 2.transformation和action流程图 3.典型的transformation和action RDD有3种操作: 1. Trandform ...
- Spark RDD/Core 编程 API入门系列之动手实战和调试Spark文件操作、动手实战操作搜狗日志文件、搜狗日志文件深入实战(二)
1.动手实战和调试Spark文件操作 这里,我以指定executor-memory参数的方式,启动spark-shell. 启动hadoop集群 spark@SparkSingleNode:/usr/ ...
- Asp.Net Core Web Api 使用 Swagger 生成 api 说明文档
最近使用 Asp.Net Core Web Api 开发项目服务端.Swagger 是最受欢迎的 REST APIs 文档生成工具之一,进入我的视野.以下为学习应用情况的整理. 一.Swagger 介 ...
- 在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务
在 ASP.NET Core Web API中使用 Polly 构建弹性容错的微服务 https://procodeguide.com/programming/polly-in-aspnet-core ...
- ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构.这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地 ...
- net core体系-API-Restful+Swagger搭建API
本篇主要简单介绍下.net core下搭建WebApi 项目结构 项目结构其实不用多说,基本上大同小异. Controller:对外暴露的契约 Business/IBussiness:业务逻辑层实现及 ...
随机推荐
- web@css盒模型详解
Margin(外边距) - 清除边框外的区域,外边距是透明的./*上 右 下 左*/ 上 左右 下 /*上下 左右*/ 四方 /Border(边框) - 围绕在内边距和内容外的边框. 可以用 ...
- 前端 -----jQuery的位置信息
08-jQuery的位置信息 jQuery的位置信息跟JS的client系列.offset系列.scroll系列封装好的一些简便api. 一.宽度和高度 获取宽度 .width() 描述:为匹配的 ...
- python字符串,列表常用操作
24天养成一个好习惯,第五天! 一.字符串需要掌握的操作 1.取值(索引取值)需要注意的是只能取,不能改 msg = 'hello world' print(msg[4]) 2.切片(顾头不顾尾) m ...
- JS跨域ajax访问
方式1:jsonp解决跨域访问 需要服务和js配合 服务 [WebMethod] public void HelloWorld2(string name) { HttpContext.Current. ...
- java虚拟机内存不足,“Could not create the Java Virtual Machine”问题解决方案
java虚拟机内存不足,"Could not create the Java Virtual Machine"问题解决方案 在运行java程序时,遇到问题"Could n ...
- 《 Oracle查询优化改写 技巧与案例 》电子工业出版社
第1章单表查询 11.1 查询表中所有的行与列 11.2 从表中检索部分行 21.3 查找空值 31.4 将空值转换为实际值 41.5 查找满足多个条件的行 51.6 从表中检索部分列 61.7 为列 ...
- Confluence 6 管理员联系表单的后台配置界面
管理员联系表单的后台配置界面截图和配置. 对输入的数据进行编辑和选择是否启用发送电子邮件给管理员 https://www.cwiki.us/display/CONFLUENCEWIKI/Configu ...
- HTML5-长按事件
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title> ...
- leetcode(js)算法之696计数二进制串
给定一个字符串 s,计算具有相同数量0和1的非空(连续)子字符串的数量,并且这些子字符串中的所有0和所有1都是组合在一起的. 重复出现的子串要计算它们出现的次数. 示例: 输入: "0011 ...
- 给artDialog插件增加动画效果
领导想给弹窗增加几种动画效果,以前用过layer弹窗,效果不错,它的动画是用的样式,实现很简单,所以把动画拷贝了过来,打包到现在的artDialog.js里... 使用方式:新增配置参数{anim:4 ...