Katalogdienst – Analyse des Beispielcodes für die Microsoft-Microservice-Architektur

零下一度
Freigeben: 2018-05-29 15:31:19
Original
3616 Leute haben es durchsucht

Im letzten Artikel haben wir über IdentityServer4 gesprochen, es gibt nicht viele Wissenspunkte. In den zukünftigen Erklärungen werden wir uns auf andere konzentrieren Wichtige Punkte. Ich hoffe, jeder versteht.

Quellcode-Analyse

Werfen wir zunächst einen Blick auf die Verzeichnisstruktur, ein sehr standardmäßiges Webapi-Verzeichnis:

Katalogdienst – Analyse des Beispielcodes für die Microsoft-Microservice-Architektur

Erster Blick auf Programm , gefolgt von IdentityService, ist ähnlich, mit dem Zusatz UseWebRoot („Pics“). Das pics-Verzeichnis ist auf webroot festgelegt, und alles andere ist gleich.

In der Konstruktionsmethode von Startup haben wir auch die Verwendung des Secret-Manager-Tools gesehen, aber es gibt noch einen weiteren Parameter. Hier sehen wir den Assembly-Typ. Tatsächlich benötigt das Geheimnis nur die userSecretsId.

In ConfigureServices sehen wir den folgenden Code:

services.AddMvc(options =>
{
	options.Filters.Add(typeof(HttpGlobalExceptionFilter));
}).AddControllersAsServices();
Nach dem Login kopieren

Dieser HTtpGlobalExceptionFilter wurde im Projekt gefunden. Dies bedeutet wahrscheinlich, dass ein Fehler vom Typ CatalogDomainException vorliegt Wenn ein Fehler auftritt, wird ein bestimmter Fehlercode zurückgegeben.

AddControllersAsServices ist eine Erweiterungsmethode, die alle Controller im Projekt in Services registriert:

        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>
Nach dem Login kopieren

Das foreach in der Mitte ist das, also wir Kann die Abhängigkeitsinjektion im Projekt verwenden. Auf jeden Controller kann auf jede Art und Weise problemlos zugegriffen werden.

Nach unten gehen:

            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>
Nach dem Login kopieren

Bei der Konfiguration von DBContext wird hier die Methode Connection Resiliency (Bounce-Verbindung) verwendet, wo Sie die Verwendung der Migration sehen können. Es verwendet MigrationsAssembly (AssemblyName). Diese Methode ähnelt in gewisser Weise dem zuvor erwähnten FluentNhibernate. Wenn während der Migration ein Fehler auftritt, werden die Auswirkungen vermieden von gelegentlichen Verbindungsausfällen, die durch die Trennung von App und Datenbank verursacht werden. Warum gibt es diesen Mechanismus? Denn wenn sich unsere Datenbank in der Cloud befindet, wie zum Beispiel Azure SQL, treten zwangsläufig Probleme mit der Netzwerkverbindung auf. Selbst wenn wir die App und die Datenbank in einem Rechenzentrum platzieren, wird es meiner Meinung nach gelegentlich zu diesem Problem kommen Wenn ein Fehler auftritt, wird der Vorgang neu gestartet, wodurch gelegentliche, durch das Netzwerk verursachte Probleme bis zu einem gewissen Grad vermieden werden. Sie können auch einige Richtlinien festlegen, um Wiederholungen beim Ausführen von Befehlen zu ermöglichen. Standardmäßig zeichnet EF nur Warnungen in der Client-Auswertung auf. Wir können diese Warnung über „ConfigureWarnings“ auslösen, und Sie können sie auch so konfigurieren, dass sie ignoriert wird.

Als nächstes sehen wir den folgenden Code:

services.Configure<catalogsettings>(Configuration);</catalogsettings>
Nach dem Login kopieren

Wir können in jedem eShop-Projekt ähnliche Anweisungen finden, die einige projektbezogene Einstellungen in Diensten registrieren und sie zu einer Umgebungsvariablen machen, die Wir können über Setting.json konfigurieren. Zusätzlich zur Konfiguration über Setting.json können wir auch eine flexible Konfiguration über Docker run –e durchführen.

Hier enthält unser CatalogSetting ein ExternalCatalogBaseUrl-Attribut. Wir können beim Ausführen von Docker den folgenden Befehl eingeben:

docke run -e "ExternalCatalogBaseUrl=http://localhost:5011/" ....
Nach dem Login kopieren

Auf diese Weise können wir es flexibel über Docker-Befehle konfigurieren, was sehr praktisch ist. Wir können auch -e verwenden, um Variablen in unserer Einstellung.json Werte zuzuweisen, z. B. ConnectionString. Klicken Sie hier, um mehr darüber zu erfahren.

            // 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());
            });
Nach dem Login kopieren

Die beiden oben genannten Codeteile konfigurieren die Strategien SwaggerGen und Cors (domänenübergreifend) und sind ein sehr praktisches Framework, das unsere API automatisch in den Webmodus konvertieren und vor uns präsentieren kann. Es kann auch debuggt werden, was sehr nützlich ist. Die Konfiguration von Cors wird hier nicht gut genutzt. Es wird empfohlen, sich an den tatsächlichen Anforderungen zu orientieren, da sonst domänenübergreifende Einstellungen keinen Sinn ergeben.

Als nächstes sahen wir eine Reihe von Vorgängen zum Hinzufügen von Diensten, die alle mit EventBus zu tun hatten. Nachdem wir es eine Weile betrachtet hatten, stellten wir fest, dass bisher nur die Protokollaktion durchgeführt wurde:

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);
}
Nach dem Login kopieren

Der obige Code bedeutet, dass wir bei einer Preisänderung EventService aufrufen, um ihn zu speichern und gleichzeitig den Vorgang aufzuzeichnen. Die PublishThroughEventBusAsync-Methode ändert den Status dieses Datensatzes in „veröffentlicht“. Derzeit weiß ich nicht, warum diese Methode verwendet wird, und ich weiß nicht, warum sie EventBus heißt. Ich habe diese Frage jedoch in der Projektausgabe angesprochen und hoffe, dass die Entwickler des Projekts mir eine Antwort geben können Antwort. Ich habe Basket.Api überprüft. In diesem Projekt wird es ein Abonnementverhalten geben. Wir werden uns die Details im nächsten Kapitel genauer ansehen.

OK, schauen wir uns noch einmal die Methode „Configure“ an. Wir können den folgenden Codeabschnitt studieren:

var context = (CatalogContext)app
            .ApplicationServices.GetService(typeof(CatalogContext));

WaitForSqlAvailability(context, loggerFactory);
Nach dem Login kopieren

Wir sehen, dass er hier den zuvor registrierten CatalogContext aufruft und nicht durchläuft new Anstatt zu instanziieren, rufen Sie die vorherige Registrierung über GetService ab, sodass auch andere Instanzen, von denen der Kontext abhängt, einbezogen werden, was sehr praktisch und einfach zu verwenden ist.

WaitForSqlAvailability-Methode besteht darin, sicherzustellen, dass die Datenbank verfügbar ist, da sie später eine Datenmigration erfordert.

CatalogService enthält 2 Controller, einer ist PicController und der andere ist CatalogController. PicController ruft nur Bilder basierend auf der ID ab. CatalogController zeigt, wie Webapi zum Ausführen von CURD verwendet wird.

运行部署

如果你要运行Catalog.Api,你必须安装MSSQL和RabbitMQ,这次我把我的系统换成了Win10 Pro,并在电脑上使用Docker安装了MSSQL-Server-Linux和RabbitMQ。安装这2个非常简单,仅仅需要输入几条命令即可:

docker run --name mssql -e &#39;ACCEPT_EULA=Y&#39; -e &#39;SA_PASSWORD=Pass@word&#39; -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
Nach dem Login kopieren

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"}
  }
}
Nach dem Login kopieren

ok,Ctrl+F5,运行一下看看:

Katalogdienst – Analyse des Beispielcodes für die Microsoft-Microservice-Architektur

当看到上面这个页面,说明你的运行正常了,你还得测试下api是否运行正常,比如Pic,比如Items。

二、docker中运行,参照上一篇的方式,先publish再build Katalogdienst – Analyse des Beispielcodes für die Microsoft-Microservice-Architektur, 不过这里要注意一点,因为你之前的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
Nach dem Login kopieren

我这里的172.17.0.2是我rabbitmq容器的ip地址,你可以通过docker inspect containerId 进行查看容器的ip。

如果一切配置都正确的话,你就可以通过浏览器http://localhost:8899 进行浏览了。

当然,除了正常浏览外,你还需测试下api是否正常。

Katalogdienst – Analyse des Beispielcodes für die Microsoft-Microservice-Architektur

困惑

在这个项目中有一些疑惑,希望大家能够给我答案。

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。

Das obige ist der detaillierte Inhalt vonKatalogdienst – Analyse des Beispielcodes für die Microsoft-Microservice-Architektur. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!