asp.net core 从单机到集群

asp.net core 从单机到集群

Intro

这篇文章主要以我的活动室预约的项目作为示例,看一下一个 asp.net core 应用从单机应用到集群部署需要做什么。

示例项目

活动室预约提供了两个版本,集群版和 单机版

单机版方便部署,不依赖其他环境,数据库使用的是 sqlite,详细部署文档可以参考:https://github.com/WeihanLi/ActivityReservation/blob/dev/docs/deploy/standalone.md

集群版,目前依赖的组件有 mysql(数据库)/redis(缓存)/elasticsearch(日志)

日志

日志原来是输出到文件中的,单机部署没有什么问题,可以直接 ssh 到机器上查看文件内容,但是如果部署到集群上,日志再输出到文件的话,排查起来可就有点麻烦了,日志是分散在多台机器上,只看某一台机器上的日志可能并不能解决问题。

基于日志这个痛点让我把日志迁移到 elasticsearch 上,日志统一输出到 es,并通过 kibana 来搜索/分析日志。

日志组件一直用的 log4net,日志输出到 es ,自己写了一个 es 的 Appender, 但是后来越来越觉得 log4net使用起来不够灵活,后来日志组件换成了 serilog,使用 serilog 就可以方便的扩展,增加日志要记录的信息,关于自定义 serilog enricher 可以参考 Serilog 自定义 Enricher 来增加记录的信息

使用 es 来存储日志还有一个好处,就是搜索日志非常的快,而且借助 kibana 可以很方便的进行统计分析

拿上篇文章的图来借用一下,下面是 kibana 基于日志的 RequestIP 来绘制的前十个访问最多的 IP 地址

640?wx_fmt=png

缓存

单机部署为了不增加系统复杂度,不引入外部依赖,单机版使用的是 MemoryCache, 集群部署,就需要引入分布式缓存,我选择的是 redis,redis 组件是基于 StackExchange.Redis 的,自己在其基础上封装了一些功能。

在我的这个示例应用中 redis 不仅仅做缓存,我还用 redis 的 hash 实现了一个类似于 asp.net 里 Application 的服务,还有 redis 的发布订阅来实现一个 eventBus 来异步处理公告的浏览记录。

单机环境下,我们用 lock 或者用信号量来实现资源在某一段时间内只能被一个请求拿到

多台机器环境下,我们需要一个分布式锁,上面引入了 redis,就用 redis 来实现一个分布式锁,分布式锁详细实现可以参考:RedLock

使用方式如下:

using (var redisLock = RedisManager.GetRedLockClient($"reservation:{reservation.ReservationPlaceId:N}:{reservation.ReservationForDate:yyyyMMdd}"))	
{	if (redisLock.TryLock())	{	var reservationForDate = reservation.ReservationForDate;	if (!IsReservationForDateAvailable(reservationForDate, isAdmin, out msg))	{	return false;	}	// ...	return true;	}	else	{	msg = "系统繁忙,请稍后重试!";	return false;	}	
}

DataProtection

微软在 .net core 下引入了 DataProtection 来保护网站的数据,你也可以用它做一些数据保护,之前做了一个简单数据保护扩展,通过 Filter 来自动实现数据的加密/解密,详细信息可以参考 asp.net core 参数保护

默认 DataProtection 的key 是保存到文件的,可能你也注意到过在 asp.net core 应用启动的时候默认会有一条日志信息如下:

640?wx_fmt=png

640?wx_fmt=png

多台机器同时部署的话,key 基本上就是不一样的,这样数据就不会被认为是安全的。

举个栗子,我的应用有一个后台使用 cookie 认证,cookie 会使用 DataProtection 的 key 进行加密,使用默认的 DataProtection 时,多台机器上(实际是k8s的多个pod) 的key 是不一样的,这就导致我在后台登录了之后,进入后台之后刷新一下可能就又跳转到登录界面,这是因为生成的 cookie ,对于一个服务来说是有效的,但是对于其他服务来说是无效的(key 不同,没有办法解密成功,认证失败),所以集群部署的时候,DataProection 是必须要设置的,放在一个统一的地方管理,我们上面已经引入了 redis,所以就把 DataProtection 的 key 放在 redis 中去保存(redis 服务可以做高可用,即使 redis 服务挂了也会重新生成一个 key,不会有什么影响)

使用到的包 Microsoft.AspNetCore.DataProtection.StackExchangeRedis,配置方式:

// DataProtection persist in redis	
services.AddDataProtection()	.SetApplicationName(ApplicationHelper.ApplicationName)	.PersistKeysToStackExchangeRedis(() => DependencyResolver.Current.ResolveService<IConnectionMultiplexer>().GetDatabase(5), "DataProtection-Keys")	;

获取用户IP

集群部署的时候,会有网关/反向代理去转发请求,这时候直接通过 HttpContext.Connection.RemoteIpAddress 获取到的 ip 地址就会是网关/反向代理的地址,并不是实际用户的地址,一般的反向代理软件会将真实的用户IP放在 X-Forwarded-For 请求头中,转发到下游真正的服务器地址,你可以从请求中直接获取 X-Forwarded-For 请求头的值,也可以使用微软提供的 ForwardedHeaders 中间件,配置方式:

public void ConfigureServices(IServiceCollection services)	
{	// ...	services.Configure<ForwardedHeadersOptions>(options =>	{	options.KnownNetworks.Clear();	options.KnownProxies.Clear();	options.ForwardLimit = null;	options.ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.All;	});	
}	
public void Configure(IApplicationBuilder app, IHostingEnvironment env)	
{    	app.UseForwardedHeaders();	// ...	
}

具体参数配置可以参考文档:https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2

Memo

其他还有一些上面并未提到,

比较常用的如 Session,如果要上集群的话,也应该有相应的分布式 session,这个应用没有用到 session,所以上面没有提(之前用极验验证码的时候有用,后来换成腾讯的验证码服务之后去掉了session)

文件上传,如果是存在本地的话,也不太合适,可能需要存在一个集中的文件服务器或者云端存储如 Azure Blob。。(网站里的公告模块的图片上传还没改,,,打算基于 github 或者 开源中国实现一个 storage )

其他暂时没想到了,想到了再补充吧。

Reference

  • https://github.com/WeihanLi/ActivityReservation

  • https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2

  • https://en.wikipedia.org/wiki/X-Forwarded-For

640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314368.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

杜教筛模板(P4213 【模板】杜教筛(Sum))

P4213 【模板】杜教筛(Sum) 套路推式子 求s(n)∑i1nf(i)∑i1n(f∗g)(i)∑i1n∑d∣if(d)g(id)∑d1n∑i1⌊nd⌋f(i)g(d)∑d1ng(d)S(⌊nd⌋)g(1)S(n)∑d2ng(d)S(⌊nd⌋)则有g(1)S(n)∑i1n(f∗g)(i)−∑d2ng(d)S(⌊nd⌋)求s(n) \sum_{i 1} ^{n}f(i)\\ \su…

[2020多校A层12.1]树(倍增/单调栈/dfs栈)

[2020多校A层12.1]树 求解树上从u到v的最长贪心上升序列,也就是只要有比它大的就选择它,可以发现这个问题性质,就是每个点对应了唯一的一个第一个比它大的点,那么我们可以向它们之间连边,然后问题就转化为求解从当前点…

通过Blazor使用C#开发SPA单页面应用程序(3)

通过Blazor使用C#开发SPA单页面应用程序(1)通过Blazor使用C#开发SPA单页面应用程序(2)今天我们来看看Blazor开发的一些基本知识。Blazor中组件的基本结构可以分为3个部分,如下所示://Counter.razor//Directives section 指令部分page "/counter&qu…

NC14250 MMSet2

MMSet2 思路 这道题目显然能够通过31051063 \times 10 ^ 5 \times 10 ^ 63105106的复杂度来暴力,这显然不能达到题目要求的复杂度,因此我们可以对题目要求我们计算的东西进行转换。 某个点到所有点集的最大距离最小,这就有点像是重心的求法…

[2020多校A层12.3]虚构推理(语言/二分/数据结构)

[2020多校A层12.3]虚构推理 给定n个时钟精确到秒,求解一个时间,使得它的指针和所有其他的时钟时针和分针分别的角度最大值最小。 一道毒瘤的二分题,看到最大值最小,我们很容易想到二分答案。然后我们的关键是check,那…

ASP.NET CORE 2.* 利用集成测试框架覆盖HttpClient相关代码

ASP.NET CORE 集成测试官方介绍我的asp.net core 项目里面大部分功能都是去调用别人的API ,大量使用HttpClient,公司单元测试覆盖率要求95%以上,很难做到不mock HttpClient 达到这个指数。以下方法是我自己总结的在单元测试里 mock httpClien…

Expected Value Again(咕咕咕)

Expected Value Again 神题!!!

[51 nod 1238] 最小公倍数之和 V3(杜教筛)

1238 最小公倍数之和 V3 推式子 ∑i1n∑j1nlcm(i,j)∑i1n∑j1nijgcd(i,j)∑d1n∑i1n∑j1nijd(gcd(i,j)d)∑d1nd∑i1nd∑j1ndij(gcd(i,j)1)∑d1nd∑i1nd∑j1ndij∑k∣gcd(i,j)μ(k)∑d1nd∑k1ndk2μ(k)∑i1ndk∑j1ndkij\sum_{i 1} ^{n} \sum_{j 1} ^{n} lcm(i, j)\\ \sum_{i…

Let's Encrypt网站推出中文版

如今很多网站都强制使用 HTTPS 加密协议访问,安全性有了很大的提高,最起码在数据传输的初始阶段数据包不会被劫持,保证了客户端与服务器端的通讯安全性。说到 HTTPS 加密协议,就不得不提 Let’s Encrypt。Let’s Encrypt 是一家不…

动态分配内存

https://www.runoob.com/cplusplus/cpp-dynamic-memory.html

[51 nod 123] 最大公约数之和 V3(杜教筛)

1237 最大公约数之和 V3 推式子 ∑i1n∑j1ngcd(i,j)∑d1nd∑i1n∑j1n(gcd(i,j)d)∑d1nd∑i1nd∑j1nd(gcd(i,j)1)∑d1nd∑i1nd∑j1nd∑k∣gcd(i,j)μ(k)∑d1nd∑k1ndμ(k)∑i1nkd∑j1nkd1套路地设tkd∑t1n(⌊nt⌋)2∑d∣tdμ(td)∑t1n(⌊nt⌋)2ϕ(t)接下来就是杜教筛求∑i1nϕ(…

使用WebDeploy部署远程IIS网站

目录 使用WebDeploy部署远程IIS网站后台服务部署服务器配置本地WebDeploy发布文件配置前端页面部署WebDeploy服务端配置WebDeploy发布文件配置使用WebDeploy部署远程网站后台服务部署服务器配置打开IIS管理器(开始->控制面板->管理工具->IIS管理器)添加网站(右键网站…

数列分块入门

文章目录数列分块入门1数列分块入门2数列分块入门3数列分块入门4数列分块入门5数列分块入门6数列分块入门7数列分块入门8数列分块入门9数列分块入门1 区间加,单点查询 分块后,维护标记,零散块暴力加,查询时输出值加标记 数列分块…

CF436F Banners(分块/凸包/单调队列)

CF436F Banners 首先有n个物品分别有ai和bi,然后定义价值为 c∗wp∗(ai大于p且bi小于c的用户个数)c*wp*(ai大于p且bi小于c的用户个数)c∗wp∗(ai大于p且bi小于c的用户个数) 然后我们需要求解对于每一个c的最大价值和对应的p 首先我们先枚举c,然后每次加…

译 | 改进 Visual Studio 及 Windows 上 .NET Core 的安装体验

点击上方蓝字关注“汪宇杰博客”原文:Lee Coward翻译:Edi Wang导语Visual Studio 2019 16.3 和 .NET Core 3.0 Preview 7 改进了 Windows 上 .NET Core 的安装体验。目标是减少计算机上可能存在的 .NET Core 版本的数量。这些改进基于客户反馈和我们自己…

F. Ivan and Burgers(前缀线性基模板)

前缀线性基模板 F. Ivan and Burgers /*Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc.h>#define mp make_pair #define pb push_back #define endl \n #define mid (l r >> 1) #define lson rt << 1, l, …

P2231 [HNOI2002]跳蚤(裴蜀定理/莫比乌斯反演)

P2231 [HNOI2002]跳蚤 给定一个长度为n1的一列数&#xff0c;第n1位为m&#xff0c;前n位小于m 求解使得他n1个数的加减可以凑出1的方案数 首先可以凑出1&#xff0c;这显然是裴蜀定理&#xff0c;推一推就发现他要求所有数的gcd为1 那么对于要求gcd恰为x的计数问题&#xff…

HDU 6579 Operation (前缀线性基模板题)

Operation 思路 只要套上前缀线性基的板子然后按照题意模拟即可&#xff0c;前缀线性基模板题了。 代码 /*Author : lifehappy */ #pragma GCC optimize(2) #pragma GCC optimize(3) #include <bits/stdc.h>#define mp make_pair #define pb push_back #define endl …

SonarQube系列三、Jenkins集成SonarQube(dotnetcore篇)

来源&#xff1a;https://www.cnblogs.com/7tiny/p/11348785.html【前言】本系列主要讲述sonarqube的安装部署以及如何集成jenkins自动化分析.netcore项目。目录如下&#xff1a;SonarQube系列一、Linux安装与部署SonarQube系列二、分析dotnet core/C#代码SonarQube系列三、Jen…

[2020多校A层11.22]party(概率期望/近似)

[2020多校A层11.22]party 非常巧妙的一个概率期望问题&#xff0c;其实运用的还是近似的思想 现在有n个物品&#xff0c;每次一个人有pi的概率选中这个物品&#xff0c;然后可以进行猜测&#xff0c;但是无论是否猜中都继续游戏&#xff0c;直到所有人都被猜中&#xff0c;求解…