집 >백엔드 개발 >C#.Net 튜토리얼 >카탈로그 서비스 - Microsoft 마이크로서비스 아키텍처 예제 코드 분석
지난 글에서는 Identity Server4를 기반으로 개발되었기 때문에 알아둘 내용이 많지 않습니다. 오늘은 Catalog Service에 대해 알아보겠습니다. .모두가 이해하길 바랍니다.
먼저 매우 표준적인 webapi 디렉터리인 디렉터리 구조를 살펴보겠습니다.
추가 UseWebRoot("Pics")가 포함된 IdentityService와 유사한 프로그램을 먼저 살펴보겠습니다. 사진 디렉토리를 설정하세요. 웹루트가 되었고, 다른 모든 것은 동일합니다.
Startup의 구성 방법에서는 비밀 관리자 도구의 사용도 보았지만 여기에는 어셈블리 유형이 하나 더 있습니다. 실제로 비밀에는 userSecretsId만 필요합니다.
ConfigureServices에서 다음 코드를 볼 수 있습니다.
services.AddMvc(options => { options.Filters.Add(typeof(HttpGlobalExceptionFilter)); }).AddControllersAsServices();
필터를 추가했습니다. 이 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.Transient<icontrolleractivator>());return builder; }</icontrolleractivator>
가운데에 있는 foreach 섹션은 프로젝트에서 종속성 주입을 통해 각 컨트롤러에 쉽게 액세스할 수 있도록 하기 위한 것입니다. .
내려가기:
services.AddDbContext<catalogcontext>(options => { options.UseSqlServer(Configuration["ConnectionString"], sqlServerOptionsAction: sqlOptions => { sqlOptions.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); //Configuring 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: });</catalogcontext>
DBContext를 구성할 때 Connection Resiliency(바운스 연결) 방식이 사용됩니다. 마이그레이션을 사용할 때 이 방식은 앞서 이야기한 FluentNhibernate와 유사합니다. , EnableRetryOnFailure는 이 작업의 실패한 시도 메커니즘을 설정합니다. 마이그레이션 중에 오류가 발생하면 자동으로 다시 시도합니다. 이 방법은 앱과 데이터베이스의 분리로 인해 발생하는 연결 오류의 영향을 방지합니다. 왜 이런 메커니즘이 있는 걸까요? 왜냐하면 우리의 데이터베이스가 Azure SQL과 같은 클라우드에 있을 때 필연적으로 네트워크 연결 문제가 발생하기 때문입니다. 앱과 데이터베이스를 데이터 센터에 두더라도 가끔 이런 문제가 발생할 것이라고 생각하므로 이제 구성할 수 있습니다. 오류가 발생하면 작업을 다시 시작하여 네트워크로 인해 가끔 발생하는 문제를 어느 정도 방지합니다. 명령을 실행할 때 재시도를 활성화하도록 일부 정책을 설정할 수도 있습니다. 기본적으로 EF는 클라이언트 평가 시 경고만 기록하도록 할 수 있으며, 이를 무시하도록 구성할 수도 있습니다.
다음으로 다음 코드를 볼 수 있습니다.
services.Configure<catalogsettings>(Configuration);</catalogsettings>
각 eShop 프로젝트에서 유사한 명령문을 찾을 수 있습니다. 이는 일부 프로젝트 관련 설정을 서비스에 등록하고 이를 환경 변수로 구성할 수 있습니다. settings.json을 통한 구성 외에도 Docker run –e를 통해 유연한 구성을 수행할 수도 있습니다.
여기에서 CatalogSetting에는 외부CatalogBaseUrl 속성이 포함되어 있습니다. docker 실행 시 다음 명령을 입력할 수 있습니다.
docke run -e "ExternalCatalogBaseUrl=http://localhost:5011/" ....
이렇게 하면 docker 명령을 통해 유연하게 구성할 수 있으며, 이는 매우 편리합니다. ConnectionString과 같은 .json의 변수에 대한 값을 클릭하면 자세히 알아볼 수 있습니다.
// 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를 웹 모드로 변환하여 우리 앞에 표시할 수도 있습니다. 디버깅이 가능합니다. 사용하기가 매우 쉽습니다. Cors의 구성은 여기서는 잘 사용되지 않습니다. 모든 요청을 허용하므로 실제 요구 사항을 따르는 것이 좋습니다. 그렇지 않으면 도메인 간 설정에 의미가 없습니다.
다음으로 EventBus와 관련된 일련의 서비스 추가 작업을 살펴보았는데, 지금까지 로그 작업만 수행되었음을 확인했습니다.
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 메서드는 이 레코드의 상태를 게시됨으로 변경합니다. 현재로서는 왜 이 방법을 사용하는지, 왜 EventBus라는 이름을 붙였는지는 알 수 없습니다. 하지만 프로젝트 이슈에 이런 질문을 올렸으니, 해당 프로젝트의 개발자들이 저에게 답변을 주실 수 있기를 바랍니다. 답변. Basket.Api를 확인했습니다. 이 프로젝트에는 구독 동작이 있으므로 다음 장에서 자세히 살펴보겠습니다.
좋아요, 다음 코드 부분을 다시 살펴보겠습니다.
var context = (CatalogContext)app .ApplicationServices.GetService(typeof(CatalogContext)); WaitForSqlAvailability(context, loggerFactory);
여기에서는 이전에 등록된 CatalogContext가 new를 통해 인스턴스화되지 않고 GetService를 통해 인스턴스화되는 것을 볼 수 있습니다. 이전 등록을 통해 컨텍스트가 의존하는 다른 인스턴스도 가져올 수 있으므로 매우 편리하고 사용하기 쉽습니다.
WaitForSqlAvailability 방법은 나중에 데이터 마이그레이션이 필요하기 때문에 데이터베이스를 사용 가능하게 만드는 것입니다.
CatalogService에는 2개의 컨트롤러가 포함되어 있습니다. 하나는 PicController이고 다른 하나는 CatalogController입니다. PicController는 ID를 기반으로 사진만 가져옵니다. CatalogController는 webapi를 사용하여 CURD를 수행하는 방법을 보여줍니다.
如果你要运行Catalog.Api,你必须安装MSSQL和RabbitMQ,这次我把我的系统换成了Win10 Pro,并在电脑上使用Docker安装了MSSQL-Server-Linux和RabbitMQ。安装这2个非常简单,仅仅需要输入几条命令即可:
docker run --name mssql -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Pass@word' -p 5433:1433 -d microsoft/mssql-server-linux docker 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": "Server=tcp:127.0.0.1,5433;Initial Catalog=Microsoft.eShopOnContainers.Services.CatalogDb;User Id=sa;Password=Pass@word", "ExternalCatalogBaseUrl": "http://localhost:5101", "EventBusConnection": "localhost", "Logging": {"IncludeScopes": false,"LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information"} } }
ok,Ctrl+F5,运行一下看看:
当看到上面这个页面,说明你的运行正常了,你还得测试下api是否运行正常,比如Pic,比如Items。
二、docker中运行,参照上一篇的方式,先publish再build 카탈로그 서비스 - Microsoft 마이크로서비스 아키텍처 예제 코드 분석, 不过这里要注意一点,因为你之前的ConnectionString和EventBusConnection都是指向本机(127.0.0.1)的,所以这里必须改一下,改成主机的ip地址或者是对应容器的ip也可以,如果您不想更改的话,也可以通过docker -e进行设置,比如:
docker run -p 8899:80 --name catalog -e "EventBusConnection=172.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。
위 내용은 카탈로그 서비스 - Microsoft 마이크로서비스 아키텍처 예제 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!