سرفصلهای دوره آموزش میکروسرویس به همراه آموزش Domain Driven Design
جلسه اول(رایگان)
- معرفی NET 6 و نحوه نصب و استفاده
- بررسی ویژگی های جدید dotNET 6 و تاثیر آنها بر روی پروژه ها
- بررسی ویژگی های جدید سی شارپ 10
- معرفی Program.cs و نحوه کانفیگ ویژگی های مختلف در آن
- بررسی Dependency Injection و سه روش Singleton، Scoped و Transient
- بررسی تاریخچه روش های تولید و عرضه سرویس های از ASMX تا gRPC
جلسه دوم
- بررسی سرعت NET 6 نسبت به نسخه های قدیمی تر
- تبدیل از نسخه های پایین تر به ورژن NET 6 :
- دستورات مربوط به ایجاد و اجرای پروژه ها در محیط VS Code
- فعال سازی ویژگی hot reload در محیط VS Code
- معرفی معماری های پرکاربرد در پیاده سازی پروژه ها
- معرفی و بررسی Clean Code Architecture
- نصب و استفاده از Template Project مربوط به Clean Architecture برای Ardalis
- نصب و استفاده از EF Core
- بررسی عملیات Migration در EF Core
- تفاوت اجرای Async-Await با حالت عادی متدها
جلسه سوم
- معرفی Swagger و مزایای استفاده از آن در Web API ها
- افزودن Annotation به Swagger
- بررسی کانفیگ های مربوط به Swagger در Program.cs
- ادامه محبث EF Core و بررسی روابط بین Entity ها
- استفاده از Data Annotation برای تعریف ویژگی های Property ها
- معرفی و استفاده از روش Fluent API در EF Core
- نصب و استفاده از Auto Mapper
- معرفی CQRS و نحوه جداسازی عملیات براساس ماهیت آنها
- استفاده از Mediator برای پیاده سازی CQRS
- پیاده سازی به صورت CQRS به کمک Mediator
- نحوه افزودن Authentication به Web API
- معرفی Token Authentication و مزایای آن
- استفاده از Refresh Token برای کامل شدن پروسه Authentication در Web API ها
جلسه چهارم
- استفاده از Mediator برای پیاده سازی Use Case ها در حالت CQRS
- نصب MediatR و استفاده از آن
- نوشتن مدل های Request و Response به همراه Handler
- معرفی الگوی Unit of Work و مشکلی که به کمک uof حل می شود
- بررسی روش های رمزنگاری داده ها در ASP.NET Core
جلسه پنجم
- پیاده سازی روش Token Authentication
- افزودن Refresh Token به پروژه برای کامل شدن چرخه Authentication
- نحوه افزودن Authorize Button به Swagger برای Set کردن Token در Swagger
- نحوه دسترسی به Claims در Token های دریافتی در Reuest Header
- بررسی نحوه پیاده سازی دسترسی های کاربر در پروژه ها
جلسه ششم
- بررسی نقشه کلی جداول User-Role-Permission برای مدیریت دسترسی ها
- پیاده سازی جداول در EF Core و نحوه ارتباط جداول با یکدیگر
- افزودن Base Controller برای افزودن Attribute های کلی Controller ها
- کارکردن با File ها و روش های ذخیره و بازیابی فایل ها در ASP.NET Core
- پیاده سازی روش ذخیره و بازیابی فایل ها با فرمت باینری روی دیتابیس
- پیاده سازی روش ذخیره و بازیابی فایل ها روی FTP
جلسه هفتم
- چالش های ذخیره فایل ها روی FTP
- روش نمایش فایل های باینری بر روی مرورگر
- رمزنگاری فایل ها قبل از ذخیره سازی
- Validation روی فایل های دریافتی
- نکات ذخیره فایل روی FTP و به صورت یک فولدر Media در مسیر اجرای پروژه
- خواندن مسیر اجرای پروژه برای ذخیره و بازیابی فایل ها
جلسه هشتم
- بررسی نکات مهم Performance در EF Core
- معرفی و استفاده از ویژگی AsNoTracking در EF Core
- افزودن Paging به کوئری های Linq
- بررسی خطای Circular در EF Core
- روش های Log زدن در ASP.NET Core
- معرفی و استفاده از Serilog
- نحوه حرکت بین Migration های EF Core و Update کردن دیتابیس
- معرفی و استفاده از Mini Profiler در ASP.NET Core
- بررسی Cors Policy در Web API ها
- نحوه افزودن Cors Policy در ASP.NET Core
- معرفی SignalR و کاربرد آن در ASP.NET Core
- مراحل استفاده از SignalR در ASP.NET Core
جلسه نهم
- شروع Domain Driven Design
- بررسی تاریخچه DDD
- معرفی و بررسی اصطلاحات مهم در DDD
- مسئله مطرح شده برای پیاده سازی چیست؟ Domain
- متخصص های کسب و کاری این مسئله چه کسانی هستند ؟ Domain Expert
- نحوه شکست مسئله پیچیده به مسائل کوچکتر : Knowledge Crunching
- مسائل پیچیده Domain یا Problem Space
- راه حل های که برای Problem Space پیدا می کنیم : Solution Space
- نیاز به یک زبان مشترک بین تیم Develop و تیم کسب و کار : Ubiquitous language
- بررسی شکستن Domain به Sub Domain ها
- Core Domain چیست ؟
- Generic Domain و Supporting Domain چیست ؟
- به کمک مفهوم Bounded Context چه کاری انجام می دهیم؟
- نقش Aggregate در DDD چیست ؟
- هر Aggregate می تواند دارای چه بخش هایی باشد؟
جلسه دهم
- نوشتن یک Aggregate با اجزای داخلی
- مروری بر Interface و Abstract Class
- بررسی کلاس Seald
- نحوه Override کردن Operator ها مانند علامت مساوی در کلاس ها
- مقایسه Validation و Invariant ها
- معرفی و بررسی انواع روابط بین کلاس ها مانند Composition و Aggregation و Association
- بررسی بخش Catalog در پیاده سازی یک فروشگاه اینترنتی
- معرفی Event Store و کاربرد آن در DDD
- ایجاد و استفاده از Event Store Context
جلسه یازدهم
- بررسی و پیاده سازی بخش Sub Domain Catalog
- مشخص کردن Use Case هایی این Sub Domain
- معرفی ویژگی Record در سی شارپ و نحوه استفاده از آن
- مقایسه حالت Mutable و Immutable
- معرفی Repository Pattern
- مزایا و معایب Generic Repository
جلسه دوازدهم
- معرفی و کاربرد Domain Event ها
- آیا نیاز داریم Event ها را در جایی ذخیره کنیم ؟
- استفاده از EventStoreDB برای نگهداری سابقه Event ها
- معرفی RabbitMQ و Kafka برای مدیریت بهتر Event ها
- کاربرد Domain Service ها
- نوشتن Domain Service
جلسه سیزدهم
- شروع بخش میکروسرویس، معرفی و تاریخچه میکروسرویس ها
- مقایسه روش Monolithic و Microservice
- چالش های پیش رو در معماری به شکل میکروسرویس
- معرفی ابزارهایی که در معماری میکروسرویس استفاده می شوند
- نحوه جداسازی سازی و شکست یک پروژه به چندین پروژه مستقل در معماری میکروسرویس
- معرفی روش gRPC
- مراحل استفاده از gRPC در پروژه ها
- نصب و استفاده از gRPC
جلسه چهاردهم
- معرفی API Gateway و نقش آن در میکروسرویس ها
- معرفی Ocelot و نحوه استفاده از آن
- بررسی ویژگی ها و امکانات Ocelot
- بررسی ویژگی Routing در Ocelot
- نحوه استفاده از Caching مربوط به Ocelot
- Load Balancer در Ocelot چگونه کار می کند ؟
- Rate Limiting چیست و در Ocelot چطور فعال می شود
- مدیریت Authentication میکروسرویس ها به کمک Ocelot
جلسه پانزدهم
- نحوه کنترل دسترسی ها در Microserice ها
- بررسی انواع روش های ارتباطی بین نرم افزارها (Synchronous و Asynchronous)
- معرفی Message Broker و وظایف آن
- معرفی RabbitMQ و Kafka
- نصب و استفاده از RabbitMQ
- اصطلاحات مهم در RabbitMQ
جلسه شانزدهم
- مثال هایی از عملیاتی که می توان توسط RabbitMQ انجام داد
- بررسی انواع روش های ارسال پیام در RabbitMQ شامل Direct - Fanout - Topic
- کارکردن با پنل مدیریت RabbitMQ برای مشاهده وضعیت صف ها و پیام ها
- کاربرد Exchange در RabbitMQ
- استفاده از Queue و کاربرد آن در RabbitMQ
- نحوه ارسال و دریافت پیام در RabbitMQ
- روش های مانیتورینگ میکروسریس ها
- معرفی و استفاده از Seq برای مانیتورینگ لاگ ها در میکروسرویس ها
- نصب و استفاده از Seq
- معرفی Dokcer و ویژگی های آن
- نصب Docker Desktop روی ویندوز
- نحوه ساخت Docker Image
- کاربرد Docker Hub چیست ؟
- Docker-Compose چه کاری انجام می دهد؟
جلسه هفدهم
- بررسی پنل Seq
- مراحل ایجاد یک Docker Image
- کاربرد فایل Docker-Compose
- معرفی و نقش Kubernetes در دنیای نرم افزار
- معرفی Pod و Node در در Kubernetes
- معرفی CI/CD و مزایای آن
- بررسی چرخه اجرا در CI/CD
- معرفی ابزارها و Library هایی که در پیاده سازی پروژه پایانی نیاز داریم
جلسه هجدهم
- بررسی و بحث های مرتبط با قرارداهای پیاده سازی نرم افزار (چالش ها و مشکلات)
- RFP در قراردادهای نرم افزار چیست ؟
- چگونه Proposal آماده کنیم و در جواب RFP ارسال کنیم؟
- اهمیت استفاده از طرح های اولیه UI به شکل ProtoType و Wireframe
- معرفی نرم افزار Figma برای طراحی صفحات یک پروژه نرم افزاری
- نحوه پیاده سازی طرح های تایید شده در تیم فنی
- هماهنگی با تیم Front برای استاندارد سازی سرویس هایی که می خواهید ارائه دهید
- نحوه مدیریت خطاها چگونه باشد؟
- فرمت خروجی API ها به چه شکلی باشد؟
- استاندارد پیاده سازی Sort و Filter را مشخص می کنیم که در همه API ها از همان مدل استفاده کنیم
- نحوه Authentication و مخصوصا کنترل دسترسی ها به چه شکلی باشد
- معرفی ABP به عنوان یک Framework قدرتمند برای پیاده سازی پروژه ها
جلسه نوزدهم
- شروع پیاده سازی پروژه فروشگاه اینترنتی
- ساخت لایه ها و بخش های مرتبط با Catalog Microservice
- بررسی Strategic Design
- بررسی Tactical Design
- مشخص کردن بخش مدیریت محصولات و ساخت میکروسرویس این بخش
- معرفی و استفاده از Mini API
جلسه بیستم
- افزودن Media به پروژه Catalog
- معرفی الگوی Specification
- استفاده از Ardalis.Specification برای پیاده سازی الگوی Specification
- افزودن Generic Repository به پروژه
- بررسی چرخه کامل ذخیره و بازیابی فایل ها
- اضافه کردن Fluent Validation برای افزودن Validation به Request Model ها
- معرفی Mapster برای بحث Mapping و مقایسه آن با Auto Mapper
- معرفی ابزار MassTransit
- معرفی Dapr و نقش مهم آن در مدیریت میکروسرویس ها
- بررسی ساختار و سرویس های Dapr
جلسه بیست و یکم
- نحوه نصب و استفاده از Dapr
- اجرای داشبورد مربوط به Dapr برای مشاهده وضعیت میکروسرویس ها
- افزودن Dapr به ASP.NET Core
- نحوه اجرای پروژه به کمک Dapr
- بررسی پروژه Catalog و نحوه تعامل به کمک Dapr
جلسه بیست و دوم
- بررسی یک پروژه کامل پیاده سازی شده به کمک Dapr
- بررسی سرویس های درگیر در روند پروژه
- نحوه تعامل سرویس ها با یکدیگر براساس امکانات Dapr
- بررسی ویژگی Service Invocation در Dapr
- کاربرد State Management در Dapr
- چگونه Publish Subscribe را به کمک Dapr انجام دهیم
- Output Binding چه کاربردی دارد؟
- Input Binding در Dapr چه موقع استفاده می شود
- مدیریت رمزها به کمک Secret Managment در Dapr
- نقش Actors در Dapr
جلسه بیست و سوم
پیاده سازی پروژه پایانی : فروشگاه اینترنتی
نوشتن FileServer : نحوه فراخوانی از طریق gRPC یا http به کمک Dapr
- آپلود فایل تکی :
- appName
- entity
- userId
- File
- byte[]
- type
- extension
- fileName
- آپلود فایل گروهی
- دانلود فایل
*** تا جلسه بیست و دوم پروژه ها روی ورژن dot net 6 بود. از این جلسه پروژه های جدید روی dot net 7 ایجاد خواهد شد.
نیازمندی های نرم افزاری برای dot net 7 :
- نصب dot net SDK 7
- آپدیت کردن Visual Studio 2022 به ورژن 17.4
جلسه بیست و چهارم
جلسه بیست و چهارم :
(جلسه دوم پیاده سازی پروژه پایانی)
نحوه ارتباط بین سرویس Catalog و FileServer : ارتباط از طریق فراخوانی سرویس یا Service Invocation
ما می توانیم به دو صورت فراخوانی مستقیم و فراخوانی به کمک Dapr این کار را انجام دهیم :
- استفاده از HttpClient
- استفاده از HttpClient ولی به کمک Dapr
مراحل افزودن Dapr به پروژه FileServer :
- نصب AspNetCore از nuget
- افزودن سرویس Dapr در cs به شکل زیر :
var daprHttpPort = Environment.GetEnvironmentVariable("DAPR_HTTP_PORT") ?? "3602";
var daprGrpcPort = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT") ?? "60002";
builder.Services.AddDaprClient(builder => builder
.UseHttpEndpoint($"http://localhost:{daprHttpPort}")
.UseGrpcEndpoint($"http://localhost:{daprGrpcPort}"));
builder.Services.AddControllers().AddDapr();
- تغییر دستور Run() به دستور app.Run("http://localhost:6002");
- افزودن فایل ps1 برای اجرای dapr و اجرای خود پروژه :
dapr run `
--app-id fileserverervice `
--app-port 6002 `
--dapr-http-port 3602 `
--dapr-grpc-port 60002 `
--config ../../dapr/config/config.yaml `
--components-path ../../dapr/components `
dotnet run
- اجرا دو دستور بالا در محیط powerShell در فولدر مربوط به روت پروژه
مراحل افزودن Dapr به پروژه Catalog :
- نصب AspNetCore از nuget
- افزودن سرویس Dapr در cs به شکل زیر :
var daprHttpPort = Environment.GetEnvironmentVariable("DAPR_HTTP_PORT") ?? "3601";
var daprGrpcPort = Environment.GetEnvironmentVariable("DAPR_GRPC_PORT") ?? "60001";
builder.Services.AddDaprClient(builder => builder
.UseHttpEndpoint($"http://localhost:{daprHttpPort}")
.UseGrpcEndpoint($"http://localhost:{daprGrpcPort}"));
builder.Services.AddControllers().AddDapr();
- تغییر دستور Run() به دستور app.Run("http://localhost:6001");
- افزودن سرویس LocalFileStorageService در فایل cs به صورت زیر برای اینکه httpClient مورد نیاز این سرویس از طریق dapr تامین شود.
builder.Services.AddTransient<IFileStorageService>(_ =>
new LocalFileStorageService(DaprClient.CreateInvokeHttpClient(
"fileserverervice", $"http://localhost:{daprHttpPort}")));
افزودن سرویس Identity به پروژه ها :
- نوشتن یک Identity Service مستقل که باید بتواند نیازهای زیر را پاسخگو باشد :
- امکان Register کردن
- امکان Authenticate
- امکان تولید توکن جدید از روی RefreshToken
- امکان Forgot Password
- مدیریت نقش ها و دسترسی های کاربران
- در سرویس Catalog یا FileServer ، باید در تمام Request ها Token به سمت این دو سرویس یا سرویس های دیگر ارسال شود و valid بودن Token سنجیده و سپس پاسخ داده شود.
جلسه بیست و پنجم
جلسه بیست و پنجم :
(جلسه سوم پیاده سازی پروژه پایانی)
نحوه مدیریت دسترسی ها :
کنترل دسترسی ها در سطح Action ها :
کاربر derambakht یا نقش Operator دسترسی های زیر را دارد :
- Catalog :
- افزودن گروه بندی محصول جدید ()
- مشاهده لیست گروه بندی محصولات
- FileServer :
- امکان آپلود فایل جدید
فرمت تعریف کلید برای دسترسی ها : {appid}-{entity}-{action}
فرمت تعریف کلید برای دسترسی ها : {entity}-{action}
مثل : category-add - در جدول permission در میکروسرویس Identity : title, key,
نحوه ارتباط Catalog با Identity :
نحوه نصب و استفاده از Redis به صورت مستقیم در پروژه ها :
- نصب Redis روی سیستم عامل یا به کمک نصب روی Docker
- افزودن Package مربوط به Redis بر روی پروژه مورد نظر
- افزودن سرویس Redis در cs پروژه مورد نظر
- Inject کردن کلاس مربوط به نوشتن و خواندن از Cache در Controller یا Service مورد نظر
1 - نصب Redis بر روی Docker :
- دریافت image مربوط به Redis از روی Docker Hub با دستور زیر :
docker pull redis
- اجرای Image برای ساختن Container مربوط به Redis بر روی Docker
docker run -d -h redis -v redis-data:/data -p 6379:6379 --name redis --restart always redis:latest /bin/sh -c redis-server --appendonly yes --requirepass "redis"
2- افزودن Package مربوط به Redis بر روی پروژه مورد نظر
Install-Package Microsoft.Extensions.Caching.StackExchangeRedis
3- افزودن سرویس Redis در Program.cs پروژه مورد نظر
builder.Services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379,password=redis";
options.InstanceName = "identitystore";
});
4- Inject کردن کلاس مربوط به نوشتن و خواندن از Cache در Controller یا Service مورد نظر
private readonly IDistributedCache _cache;
[HttpGet("Test")]
public async Task<IActionResult> Test()
{
var options = new DistributedCacheEntryOptions();
options.SetSlidingExpiration(TimeSpan.FromMinutes(1));
options.SetAbsoluteExpiration(TimeSpan.FromMinutes(10));
await _cache.SetStringAsync("ali", "123456", options);
return Ok();
}
[HttpGet("Test2")]
public async Task<string> Test2()
{
var value = await _cache.GetStringAsync("ali");
return value;
}
نحوه استفاده از ویژگی State-Management (Cache) مربوط به Dapr در پروژه ها :
- در ابتدا باید فایل dapr run برای پروژه مورد نظر نوشته شود :
dapr run `
--app-id identityservice `
--app-port 6005 `
--dapr-http-port 3605 `
--dapr-grpc-port 60005 `
--config ../../dapr/config/config.yaml `
--components-path ../../dapr/components `
- در محلی که نیاز داریم مقداری را در state به کمک dapr ذخیره کنیم کلاس DaprClient را inject می کنیم :
private readonly DaprClient _daprClient;
- سپس برای نوشتن مقدار در state از دستور زیر استفاده می کنیم :
await _daprClient.SaveStateAsync<List<string>>(DAPR_STORE_NAME,stateKey, item.PermissioKeys);
- در ادامه برای خواندن مقدار state در همان Application یا Application دیگر از دستور زیر استفاده می کنیم :
var appPermissions= await _daprClient.GetStateAsync<List<string>>(DAPR_STORE_NAME, stateKey.ToLower());
*** حتما باید کانفیگ های زیر را در فایل های مربوط به کانفیگ dapr انجام دهیم :
فایل اول : statestore.yaml : در داخل این فایل مشخص می کنیم که برای state از کدام بستر مثلا Redis با چه ویژگی هایی و چه application های مجاز.
فایل دوم : secrets-file.yaml : مشخص می کنیم که ویژگی های امنیتی مانند password از کدام json فایل خوانده شود که در این مثال همان فایل secrets.json می باشد.
فایل سوم : secrets.json : همه کدهای امنیتی مانند رمزهای عبور Redis یا هر ابزار دیگری مثل SMTP Mail Server را نگهداری می کنیم.
*** در این فایل ها باید توجه زیادی به یکی بودن namespace ها و همچنین بخش scopes که مشخص می کند کدام میکروسرویس ها اجازه استفاده دارند را داشته باشیم.
پایان جلسه بیست و پنجم
جلسه بیست و ششم
جلسه بیست و ششم :
نحوه نوشتن و مدیریت Log در میکروسرویس ها :
مراحل تهیه و استفاده از Log ها :
- تولید لاگ مناسب و کاربری
- جمع آوری لاگ در یک سرور
- یکسان سازی و هم شکل کردن لاگ های تولیدی توسط App های مختلف
- کوئری زدن رولاگ ها و ساخت داشبوردهای لاگ برای استفاده نگهداری از سیستم ها و همینطور استفاده تیم Business
انواع لاگ قابل استفاده :
- لاگ هایی که توسط Application ها تولید می شوند.
- لاگی که میزان استفاده و وضعیت Application ما را نشان می دهد.(به کمک Metrics در ASP.NET)
- لاگ هایی که وضعیت منابع سرور را نشان می دهد.
- لاگ هایی که وضعیت شبکه را به ما نشان می دهند.
راه حل جامع برای مدیریت Log ها : استفاده از ELK، یکی از بهترین راه حل های برای مدیریت Log در سیستم های نرم افزاری باشد.
ELK Stack : راه حلی جامع از شرکت Elasticsearch co برای مدیریت لاگ ها.
- Log Beats : وظیفه جمع آوری لاگ از کانال های مختلف را دارد. برای لاگ های مختلف ما Beat های مرتبط داریم. مثلا FileBeat وظیفه جمع آوری لاگ ها به صورت فایل را دارد.
- Logstash : لاگ های جمع آوری را شده را یکسان سازی (هم شکل سازی) می کند و در داخل دیتابیس Elasticsearch قرار می دهد.
-Elasticseach : دیتابیس No-SQL است که لاگ های جمع آوری شده و یکسان سازی شده را در آن قرار می دهیم.
- Kibana : ابزاری برای داشبوردسازی روی داده هایی که در داخل Elasticsearch قرار گرفته است.
مشکل جستجو در داده های توسط کاربر : کاربر یک درخواست یا جستجویی انجام می دهد که در پشت صحنه ما باید روی بیش از یک دیتابیس جستجو انجام دهیم(به خاطر اینکه به ازای هر میکروسرویس، یک دیتابیس جداگانه طراحی کرده ایم.)
راه حل درست : داده های مرتبط با هم که در جستجوی کاربران و از دید کاربر به صورت یک entity واحد به همراه وابستگی ها است، باید در زمان ذخیره این داده به صورت index شده در دیتابیس Elasticsearch هم ذخیره شود و سپس کوئری های جستجوی ما روی این دیتابیس اجرا شود.
خسته نباشید.
جلسه آینده پیاده سازی جستجوی پیشرفته به کمک Elasticsearch