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 地址

缓存

单机部署为了不增加系统复杂度,不引入外部依赖,单机版使用的是 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 应用启动的时候默认会有一条日志信息如下:

多台机器同时部署的话,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

asp.net core 从单机到集群的更多相关文章

  1. Kubernetes初探[1]:部署你的第一个ASP.NET Core应用到k8s集群

    Kubernetes简介 Kubernetes是Google基于Borg开源的容器编排调度引擎,作为CNCF(Cloud Native Computing Foundation)最重要的组件之一,它的 ...

  2. (视频)asp.net core系列之k8s集群部署视频

    0.前言 应许多网友的要求,特此录制一下k8s集群部署的视频.在录制完成后发现视频的声音存在一点瑕疵,不过不影响大家的观感. 一.视频说明 1.视频地址: 如果有不懂,或者有疑问的欢迎留言.视频分为两 ...

  3. Greenplum源码编译安装(单机及集群模式)完全攻略

    公司有个项目需要安装greenplum数据库,让我这个gp小白很是受伤,在网上各种搜,结果找到的都是TMD坑货帖子,但是经过4日苦战,总算是把greenplum的安装弄了个明白,单机及集群模式都部署成 ...

  4. 玩转nodeJS系列:使用cluster创建nodejs单机多核集群(多进程)

    前言: nodejs提供了cluster集群(支持端口共享的多进程),cluster基于child_process,process二次封装,方便我们使用该功能实现单机nodejs的web集群. 1.c ...

  5. Zookeeper单机伪集群

    Zookeeper单机伪集群 1.配置 zookeeper下载地址:http://apache.mirrors.lucidnetworks.net/zookeeper/ 可以选择需要的版本,我下载的是 ...

  6. 【运维技术】Zookeeper单机以及集群搭建教程

    Zookeeper单机以及集群搭建教程 单机搭建 单机安装以及启动 安装zookeeper的前提是必须有java环境 # 选择目录进行下载安装 cd /app # 下载zk,可以去官方网站下载,自己上 ...

  7. redis在Windows下以后台服务一键搭建集群(单机--伪集群)

    redis在Windows下以后台服务一键搭建集群(单机--伪集群) 一.概述 此教程介绍如何在windows系统中同一台机器上布置redis伪集群,同时要以后台服务的模式运行.布置以脚本的形式,一键 ...

  8. Spark Tachyon编译部署(含单机和集群模式安装)

    Tachyon编译部署 编译Tachyon 单机部署Tachyon 集群模式部署Tachyon 1.Tachyon编译部署 Tachyon目前的最新发布版为0.7.1,其官方网址为http://tac ...

  9. 原创 | 手摸手带您学会 Elasticsearch 单机、集群、插件安装(图文教程)

    欢迎关注笔者的公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site/ ...

随机推荐

  1. 7月18日刷题记录 二分答案跳石头游戏Getting

    通过数:1 明天就要暑假编程集训啦~莫名开心 今天做出了一道 二分答案题(好艰辛鸭) 1049: B13-二分-跳石头游戏(二分答案) 时间限制: 5 Sec  内存限制: 256 MB提交: 30  ...

  2. 自定义View之开关

    资源文件 首先我们需要有两个图片文件,分别是开关的背景和开关的滑块 自定义View 1.写一个类继承View 2.copy该类的全路径名在布局文件使用, 3.找到这个控件,设置初始信息 4.根据需求绘 ...

  3. C#3.0新增功能10 表达式树 04 执行表达式

    连载目录    [已更新最新开发文章,点击查看详细] 表达式树 是表示一些代码的数据结构. 它不是已编译且可执行的代码. 如果想要执行由表达式树表示的 .NET 代码,则必须将其转换为可执行的 IL ...

  4. “朕赐给你,才是你的;朕不给,你不能抢”--custome role在Azure权限管理中的简单实践

    在开始详细讨论技术问题之前,有一些个人观点想发表一下: ---作为一个甲方云平台的掌控着,如果任何事情你都是让partner全部帮你搞定,自己既不审核也不研究,那无论是对于公司还是个人发展来说都是没任 ...

  5. C#写好的类库dll在别人调用的时候也能看到注释的方法

    1.用///的方法添加注释 2.项目的属性里面,要选上"生成XML注释文档" 菜单 Project -> 'xxxx' Properties -> Build -> ...

  6. lnmp php使用命令行去备份数据库

    <?php //备份数据库we8和foshan $time = date("Y-m-d",time()); $backtime = date("Y-m-d" ...

  7. 比特币and区块链

    比特币简介 比特币(Bitcoin:比特金)最早是一种网络虚拟货币,可以购买现实生活当中的物品.它的特点是分散化.匿名.只能在数字世界使用,不属于任何国家和金融机构,并且不受地域的限制,可以在世界上的 ...

  8. 第三章 基础算法和数据结构高频题 I

    区间类问题 1 Missing Interval public List<String> findMissingRanges(int[] nums, int lower, int uppe ...

  9. android 界面提示框架WisdomProgressHUD,为金典而生

    一:简述 今天给android开发者们,推荐一个金典的界面提示框架WisdomProgressHUD,使用简洁方便. WisdomProgressHUD 是一个半透明的 HUD 指示器. Wisdom ...

  10. RabbitMQ搭建单机及集群

    1,基本环境配置 hosts 文件 免密登录 2,访问官网 https://www.rabbitmq.com/download.html 3, 4,安装依赖 yum -y install make g ...