通辽网站建设招聘,青岛建站软件,房和城乡建设部网站,万网x3安装wordpress上一篇我们说了Identity Service#xff0c;因为其基于IdentityServer4开发的#xff0c;所以知识点不是很多#xff0c;今天我们来看下Catalog Service#xff0c;今后的讲解都会把不同的、重点的拿出来讲#xff0c;希望大家明白。
源码分析
我们先看下它的目录结构因为其基于IdentityServer4开发的所以知识点不是很多今天我们来看下Catalog Service今后的讲解都会把不同的、重点的拿出来讲希望大家明白。
源码分析
我们先看下它的目录结构很标准的webapi目录 首先看下Program跟IdentityService类似多了一个UseWebRoot(“Pics”)把pics这个目录设置成了webroot其他都一样。
在Startup的构造方法中我们也看到了使用了secret manager tool但是多了一个参数在这里我们看到的是Assembly类型其实secret只需要其中的userSecretsId而已。
在ConfigureServices中我们看到如下代码
services.AddMvc(options
{ options.Filters.Add(typeof(HttpGlobalExceptionFilter));
}).AddControllersAsServices();
添加了一个filter这个HTtpGlobalExceptionFilter可以在项目中找到大概的意思就是遇到抛出CatalogDomainException类型的错误时返回特定的错误码。
AddControllersAsServices这个扩展方法是把项目中的Controller都注册到Services中我们看下源码 public static IMvcCoreBuilder AddControllersAsServices( this IMvcCoreBuilder builder){ var feature new ControllerFeature();builder.PartManager.PopulateFeature(feature); foreach (var controller in feature.Controllers.Select(c c.AsType())){builder.Services.TryAddTransient(controller, controller);}builder.Services.Replace(ServiceDescriptor.TransientIControllerActivator, ServiceBasedControllerActivator()); return builder;
} 中间那段foreach就是这样我们在项目中通过依赖注入方式都能方便的访问到各个controller了。
Going down: services.AddDbContextCatalogContext(options {options.UseSqlServer(Configuration[ConnectionString],sqlServerOptionsAction: sqlOptions {sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); //Configuring Connection Resiliency: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-resiliency sqlOptions.EnableRetryOnFailure(maxRetryCount: 5, maxRetryDelay: TimeSpan.FromSeconds(30), errorNumbersToAdd: null);}); // Changing default behavior when client evaluation occurs to throw. // Default in EF Core would be to log a warning when client evaluation is performed. options.ConfigureWarnings(warnings warnings.Throw(RelationalEventId.QueryClientEvaluationWarning)); //Check Client vs. Server evaluation: https://docs.microsoft.com/en-us/ef/core/querying/client-eval}); 对DBContext的配置的时候这里使用了Connection Resiliency弹回连接的方式其中可以看到使用migration的时候它使用了MigrationsAssembly(AssemblyName)这种方式跟我之前讲的FluentNhibernate有点类似,EnableRetryOnFailure设置了这个Action的失败尝试机制如果Migration的时候遇到Failure就会自动重试这种方式避免了app与database分离造成的连接偶尔失败造成的影响。为什么会有这个机制呢因为当我们的database在云端的时候比如Azure SQL不可避免的会出现网络连接问题即使我们把app和database放在一个数据中心中我相信偶尔也会有这个问题我们现在可以通过配置使其如果遇到失败就会重新操作一定程度避免了网络偶尔造成的问题。你也可以设置一些策略使其能够在运行命令的时候能够进行重试EF默认情况下只是记录client evaluation中的warns我们可以通过ConfigureWarnings使其抛出这个警告你也可以配置成忽略。
接下来我们看到如下代码
services.ConfigureCatalogSettings(Configuration);
我们可以在eShop的各个项目中都能找到类似的语句它会把一些项目相关的Settings注册到services中使其成为环境变量我们可通过setting.json进行配置。除了通过setting.json进行配置我们还能通过Docker run –e 进行灵活化配置。
在这里我们的CatalogSetting含有一个ExternalCatalogBaseUrl属性我们在docker run的时候可以输入如下命令
docke run -e ExternalCatalogBaseUrlhttp://localhost:5011/ ....
这样就能灵活的通过docker命令进行配置了非常方便我们也可以通过-e对我们setting.json中的变量进行赋值比如ConnectionString,你可以通过点击了解更多相关内容。 // Add framework services.services.AddSwaggerGen();services.ConfigureSwaggerGen(options {options.DescribeAllEnumsAsStrings();options.SingleApiVersion(new Swashbuckle.Swagger.Model.Info(){Title eShopOnContainers - Catalog HTTP API,Version v1,Description The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample,TermsOfService Terms Of Service});});services.AddCors(options {options.AddPolicy(CorsPolicy,builder builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials());}); 上面两段代码分别配置了SwaggerGen和Cors跨域策略SwaggenGen是一个非常实用的框架它能自动把我们的api转为web方式呈现在我们眼前还能进行调试非常好用。Cors的配置这里用的不好它允许了所有请求建议还是按照实际需求来吧否则没有跨域设置的意义了。
接下来我们看到了一系列的add service的操作都是关于EventBus的稍微看了下发现目前只做了log的动作我们看下代码
if (raiseProductPriceChangedEvent) // Save and publish integration event if price has changed{ //Create Integration Event to be published through the Event Busvar priceChangedEvent new ProductPriceChangedIntegrationEvent(catalogItem.Id, productToUpdate.Price, oldPrice); // Achieving atomicity between original Catalog database operation and the IntegrationEventLog thanks to a local transactionawait _catalogIntegrationEventService.SaveEventAndCatalogContextChangesAsync(priceChangedEvent); // Publish through the Event Bus and mark the saved event as publishedawait _catalogIntegrationEventService.PublishThroughEventBusAsync(priceChangedEvent);
} 上面的代码意思是在价格有变动的时候我们就调用EventService进行保存同时对操作进行了记录。PublishThroughEventBusAsync方法则对这条记录的State更改为published。目前来说我不太清楚为何要用这种方式也不知道为何取名为EventBus不过我在项目的issue中已经提出了这个问题希望项目的开发者们能给我一个答案。我有查看了Basket.Api在这个项目中会有订阅行为具体的等到下一章我们再仔细看看。
ok我们再看下Configure方法下面一段代码我们可以学习下
var context (CatalogContext)app.ApplicationServices.GetService(typeof(CatalogContext));WaitForSqlAvailability(context, loggerFactory);
我们看到在这里它调用了之前注册的CatalogContext它并没有通过new进行实例化而是通过GetService的方式获取之前的注册这样context所依赖的其他实例也一并带进来了非常方便好用。
WaitForSqlAvailability方法是对数据库可用进行尝试因为后面它需要进行数据迁移。
CatalogService包含了2个Controller一个是PicController一个是CatalogControllerPicController仅仅是根据ID获取了图片CatalogController展示了用webapi如何做CURD。
运行部署
如果你要运行Catalog.Api你必须安装MSSQL和RabbitMQ这次我把我的系统换成了Win10 Pro并在电脑上使用Docker安装了MSSQL-Server-Linux和RabbitMQ。安装这2个非常简单仅仅需要输入几条命令即可
docker run --name mssql -e ACCEPT_EULAY -e SA_PASSWORDPassword -p 5433:1433 -d microsoft/mssql-server-linuxdocker run -d --hostname my-rabbit --name rabbitmq -p 8080:15672 -p 5672:5672 rabbitmq:3-management
ok我们使用docker创建了mssql和rabbitmq这里注意一下我把mssql的端口映射到了本机的5433上还有rabbitmq的管理页面我映射到了本机的8080端口你可以通过http://localhost:8080 进行访问。
上一篇我们说过我们可以通过iisexpress/Kestrel或者docker的形式运行因为牵涉到配置所以这两种方式的运行有些不同。
一、iisExpress或Kestrel方式下因为刚刚我们把mssql和rabbitmq的端口都映射到了本机所以我们只需要在setting.json中把数据库连接和rabbitmq的地址指向本机即可如下
{ ConnectionString: Servertcp:127.0.0.1,5433;Initial CatalogMicrosoft.eShopOnContainers.Services.CatalogDb;User Idsa;PasswordPassword, ExternalCatalogBaseUrl: http://localhost:5101, EventBusConnection: localhost, Logging: { IncludeScopes: false, LogLevel: { Default: Debug, System: Information, Microsoft: Information}}
} okCtrlF5运行一下看看 当看到上面这个页面说明你的运行正常了你还得测试下api是否运行正常比如Pic比如Items。
二、docker中运行参照上一篇的方式先publish再build image 不过这里要注意一点因为你之前的ConnectionString和EventBusConnection都是指向本机127.0.0.1的所以这里必须改一下改成主机的ip地址或者是对应容器的ip也可以如果您不想更改的话也可以通过docker -e进行设置比如
docker run -p 8899:80 --name catalog -e EventBusConnection172.17.0.2 -d catalog:01
我这里的172.17.0.2是我rabbitmq容器的ip地址你可以通过docker inspect containerId 进行查看容器的ip。
如果一切配置都正确的话你就可以通过浏览器http://localhost:8899 进行浏览了。
当然除了正常浏览外你还需测试下api是否正常。 困惑
在这个项目中有一些疑惑希望大家能够给我答案。
Connection Resiliency我看了很久字面意思是弹性连接但我觉得用弹性好像不太适合一般来讲我们说的弹性都是指架构或者系统的伸缩性我一开始也是从这个角度去了解但看了很多文章觉得它只是让我们在启动的时候设置一些重试策略在后面调用中可使用此策略策略会根据你设置的重试次数、延迟时间等去自动重试避免因为偶尔的错误造成的影响所以觉得用弹回比较恰当。
EventBus我感觉很奇怪为什么一定要取这个名字呢在Android中很明确的它是进行订阅发布消息传递可以解耦发布者和订阅者但在Catalog.Api里变成了记录操作没有看到解耦也没有看到订阅。在我的理解中应该在Startup进行订阅操作发布者CatalogController在进行update操作的时候订阅者进行add log动作但在这个实例中我看到的是同步进行了这些操作所以很不解。
Mssql-server-linux当你用Docker安装了以后你却不能使用visual studio 2017的sql server data tools进行查询只能进行连接为了查看效果还需要安装Microsoft Sql Server Management Studio必须17版本以后进行查看数据。
写在最后
这次的文章来的比较晚一方面有点忙另一方面就是上面提到的困惑面对困惑我试着去解答但有时候真的无法解答所以提出来集思广益。
后面可能会比较慢需要学习的东西真多一边写一边学习成为这次系列的乐趣现在每天坚持6公里快走夜走能够是我保持头脑清晰思考项目中的疑问现在发觉生活越发有趣。
或许有很多人觉得只看了Startup就够了吗其实真不够我目前先把框架的源码过一遍后面会分篇讲述比如Connection Resiliency。
最后应大家要求我建了一个QQ群376248054大家可以进来一起探讨一起学习
相关文章
事件总线Event Bus知多少Identity Service - 解析微软微服务架构eShopOnContainers二开篇有益-解析微软微服务架构eShopOnContainers一
原文地址http://www.cnblogs.com/inday/p/catalog-service-eshopOnContainers.html .NET社区新闻深度好文微信中搜索dotNET跨平台或扫描二维码关注