日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

在ASP.NET Core微服务架构下使用数据库切分和扩展

發(fā)布時(shí)間:2023/12/4 asp.net 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 在ASP.NET Core微服务架构下使用数据库切分和扩展 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

原文鏈接:https://itnext.io/how-to-use-database-sharding-and-scale-an-asp-net-core-microservice-architecture-22c24916590f

微服務(wù)的一大優(yōu)點(diǎn)是,它們可以獨(dú)立擴(kuò)展。本文展示了擴(kuò)展一個(gè)微服務(wù)及其數(shù)據(jù)庫的好處和挑戰(zhàn)

您將創(chuàng)建一個(gè)示例應(yīng)用程序并手動(dòng)實(shí)現(xiàn)應(yīng)用程序?qū)臃制K故玖巳绾胃鶕?jù)用例和數(shù)據(jù)模型選擇分片Key。這有助于將相同的原理應(yīng)用到具有集成擴(kuò)展(如MongoDB等)的DBMS上。

1.用例和數(shù)據(jù)模型

示例應(yīng)用程序由一個(gè)User和Post微服務(wù)組成。它們通過消息交流:?

User微服務(wù)處理添加和修改用戶。Post微服務(wù)處理查看和添加帖子。因?yàn)榕cPost微服務(wù)的交互要多得多,所以,當(dāng)應(yīng)用程序的負(fù)載增加時(shí),Post微服務(wù)將成為第一個(gè)需要擴(kuò)展的微服務(wù)。

作者的名字是PostService綁定上下文的一部分,因此也是Post微服務(wù)的一部分。在User微服務(wù)中添加和修改作者。User微服務(wù)在添加新用戶或更改用戶名時(shí)發(fā)送事件。

PostService的邏輯數(shù)據(jù)模型

用戶可以分類寫文章。他們還可以按類別閱讀帖子,包括作者姓名。最新的帖子在上面。分類是固定的,很少改變。

基于這些用例,我決定按類別劃分?jǐn)?shù)據(jù)庫分片:

2.實(shí)現(xiàn)微服務(wù)

創(chuàng)建解決方案并添加名為“PostService”的ASP.NET Core 5 Web API項(xiàng)目。禁用HTTPS并激活OpenAPI支持。

安裝以下NuGet軟件包:

  • Microsoft.EntityFrameworkCore.Tools

  • MySql.EntityFrameworkCore

  • Newtonsoft.Json

創(chuàng)建實(shí)體

Post實(shí)體的索引可以加快檢索某個(gè)類別中最新的帖子:

using?Microsoft.EntityFrameworkCore; using?System.ComponentModel.DataAnnotations;namespace?PostService.Entities {[Index(nameof(PostId),?nameof(CategoryId))]public?class?Post{public?int?PostId?{?get;?set;?}public?string?Title?{?get;?set;?}public?string?Content?{?get;?set;?}public?int?UserId?{?get;?set;?}public?User?User?{?get;?set;?}[Required]public?string?CategoryId?{?get;?set;?}public?Category?Category?{?get;?set;?}} }

User實(shí)體中的版本稍后將幫助處理無序消息:

namespace?PostService.Entities {public?class?User{public?int?ID?{?get;?set;?}public?string?Name?{?get;?set;?}public?int?Version?{?get;?set;?}} }namespace?PostService.Entities {public?class?Category{public?string?CategoryId?{?get;?set;?}} }

創(chuàng)建PostServiceContext

using?Microsoft.EntityFrameworkCore;namespace?PostService.Data {public?class?PostServiceContext?:?DbContext{private?readonly?string?_connectionString;public?PostServiceContext(string?connectionString){_connectionString?=?connectionString;}protected?override?void?OnConfiguring(DbContextOptionsBuilder?optionsBuilder){optionsBuilder.UseMySQL(_connectionString);}public?DbSet<PostService.Entities.Post>?Post?{?get;?set;?}public?DbSet<PostService.Entities.User>?User?{?get;?set;?}public?DbSet<PostService.Entities.Category>?Category?{?get;?set;?}} }

在appsettings.Development.json中添加連接字符串(在調(diào)試期間將使用兩個(gè)分片)

{"Logging":?{"LogLevel":?{"Default":?"Information","Microsoft":?"Warning","Microsoft.Hosting.Lifetime":?"Information"}},"PostDbConnectionStrings":?{"Shard0":?"server=localhost;?port=3310;?database=post;?user=root;?password=pw;?Persist?Security?Info=False;?Connect?Timeout=300","Shard1":?"server=localhost;?port=3311;?database=post;?user=root;?password=pw;?Persist?Security?Info=False;?Connect?Timeout=300"????} }

添加DataAccess代碼

GetConnectionString(string category)計(jì)算CategoryId的哈希值。哈希的第一部分將配置的分片數(shù)(連接字符串)取模,從而確定給定類別的分片。

InitDatabase刪除并重新創(chuàng)建所有分片中的所有表,并插入虛擬用戶和類別。

其他方法用于創(chuàng)建和加載帖子。

using?Microsoft.AspNetCore.Mvc; using?Microsoft.EntityFrameworkCore; using?Microsoft.Extensions.Configuration; using?PostService.Entities; using?System; using?System.Collections.Generic; using?System.Linq; using?System.Security.Cryptography; using?System.Text; using?System.Threading.Tasks;namespace?PostService.Data {public?class?DataAccess{private?readonly?List<string>?_connectionStrings?=?new?List<string>();public?DataAccess(IConfiguration?configuration){var?connectionStrings?=?configuration.GetSection("PostDbConnectionStrings");foreach(var?connectionString?in?connectionStrings.GetChildren()){Console.WriteLine("ConnectionString:?"?+?connectionString.Value);_connectionStrings.Add(connectionString.Value);}}public?async?Task<ActionResult<IEnumerable<Post>>>?ReadLatestPosts(string?category,?int?count){using?var?dbContext?=?new?PostServiceContext(GetConnectionString(category));return?await?dbContext.Post.OrderByDescending(p?=>?p.PostId).Take(count).Include(x?=>?x.User).Where(p?=>?p.CategoryId?==?category).ToListAsync();}public?async?Task<int>?CreatePost(Post?post){using?var?dbContext?=?new?PostServiceContext(GetConnectionString(post.CategoryId));dbContext.Post.Add(post);return?await?dbContext.SaveChangesAsync();}public?void?InitDatabase(int?countUsers,?int?countCategories){foreach?(var?connectionString?in?_connectionStrings){using?var?dbContext?=?new?PostServiceContext(connectionString);dbContext.Database.EnsureDeleted();dbContext.Database.EnsureCreated();for?(int?i?=?1;?i?<=?countUsers;?i++){dbContext.User.Add(new?User?{?Name?=?"User"?+?i,?Version?=?1?});dbContext.SaveChanges();}for?(int?i?=?1;?i?<=?countCategories;?i++){dbContext.Category.Add(new?Category?{?CategoryId?=?"Category"?+?i?});dbContext.SaveChanges();}}}private?string?GetConnectionString(string?category){using?var?md5?=?MD5.Create();var?hash?=?md5.ComputeHash(Encoding.ASCII.GetBytes(category));var?x?=?BitConverter.ToUInt16(hash,?0)?%?_connectionStrings.Count;return??_connectionStrings[x];}} }

在Startup.cs中將DataAccess注冊為單例

public?class?Startup {...public?void?ConfigureServices(IServiceCollection?services){services.AddControllers();services.AddSwaggerGen(c?=>{c.SwaggerDoc("v1",?new?OpenApiInfo?{?Title?=?"PostService",?Version?=?"v1"?});});services.AddSingleton<DataAccess>();}---

創(chuàng)建PostController

它使用DataAccess類

using?Microsoft.AspNetCore.Mvc; using?PostService.Data; using?PostService.Entities; using?System.Collections.Generic; using?System.Threading.Tasks;namespace?PostService.Controllers {[Route("api/[controller]")][ApiController]public?class?PostsController?:?ControllerBase{private?readonly?DataAccess?_dataAccess;public?PostsController(DataAccess?dataAccess){_dataAccess?=?dataAccess;}[HttpGet]public?async?Task<ActionResult<IEnumerable<Post>>>?GetLatestPosts(string?category,?int?count){return?await?_dataAccess.ReadLatestPosts(category,?count);}[HttpPost]public?async?Task<ActionResult<Post>>?PostPost(Post?post){await?_dataAccess.CreatePost(post);return?NoContent();}[HttpGet("InitDatabase")]public?void?InitDatabase([FromQuery]?int?countUsers,?[FromQuery]?int?countCategories){_dataAccess.InitDatabase(countUsers,?countCategories);}} }

3. 用PostService訪問數(shù)據(jù)庫

安裝Docker Desktop。

創(chuàng)建兩個(gè)MySql容器

C:\dev>docker?run?-p?3310:3306?--name=mysql1?-e?MYSQL_ROOT_PASSWORD=pw?-d?mysql:5.6 C:\dev>docker?run?-p?3311:3306?--name=mysql2?-e?MYSQL_ROOT_PASSWORD=pw?-d?mysql:5.6

在Visual Studio中啟動(dòng)Post服務(wù)。瀏覽器在打開http://localhost:5001/swagger/index.html

使用swagger UI與服務(wù)交互:

初始化包含100個(gè)用戶和10個(gè)類別的數(shù)據(jù)庫:?

在“Category1”下增加一個(gè)帖子:

{"title":?"MyTitle","content":?"MyContent","userId":?1,"categoryId":?"Category1" }

閱讀“Category1”中排名前10位的帖子:

連接到數(shù)據(jù)庫容器并驗(yàn)證哪個(gè)數(shù)據(jù)庫包含新的帖子

C:\dev>docker?container?exec?-it?mysql1?/bin/sh

使用密碼“pw”登錄MySql并讀取帖子:?

第二個(gè)實(shí)例不包含任何帖子:

C:\dev>docker?container?exec?-it?mysql2?/bin/sh

4.最后的想法和展望

您創(chuàng)建了一個(gè)可工作的應(yīng)用程序,實(shí)現(xiàn)了應(yīng)用程序?qū)臃制?#xff0c;并使用了分片Key的概念。

這只是一個(gè)示例應(yīng)用程序。您必須調(diào)整代碼才能在生產(chǎn)環(huán)境中使用它。

在第二部分中,您將縮放并運(yùn)行微服務(wù)和數(shù)據(jù)庫的多個(gè)容器實(shí)例。您將使用docker compose和負(fù)載平衡器。然后,您將運(yùn)行JMeter負(fù)載測試,以查看應(yīng)用程序在使用不同數(shù)量的實(shí)例時(shí)是如何伸縮的。最后,您將通過RabbitMQ模擬來自用戶微服務(wù)的用戶事件。

歡迎關(guān)注我的個(gè)人公眾號(hào)”My IO“

總結(jié)

以上是生活随笔為你收集整理的在ASP.NET Core微服务架构下使用数据库切分和扩展的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。