建品牌网站公司,wordpress自动保存图片,页面设计的线条,百度推广效果asp.net core 从单机到集群Intro这篇文章主要以我的活动室预约的项目作为示例#xff0c;看一下一个 asp.net core 应用从单机应用到集群部署需要做什么。示例项目活动室预约提供了两个版本#xff0c;集群版和 单机版单机版方便部署#xff0c;不依赖其他环境#xff0c;数… 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 集群部署就需要引入分布式缓存我选择的是 redisredis 组件是基于 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(() gt; DependencyResolver.Current.ResolveServicelt;IConnectionMultiplexergt;().GetDatabase(5), DataProtection-Keys) ;获取用户IP集群部署的时候会有网关/反向代理去转发请求这时候直接通过 HttpContext.Connection.RemoteIpAddress 获取到的 ip 地址就会是网关/反向代理的地址并不是实际用户的地址一般的反向代理软件会将真实的用户IP放在 X-Forwarded-For 请求头中转发到下游真正的服务器地址你可以从请求中直接获取 X-Forwarded-For 请求头的值也可以使用微软提供的 ForwardedHeaders 中间件配置方式public void ConfigureServices(IServiceCollection services)
{ // ... services.Configurelt;ForwardedHeadersOptionsgt;(options gt; { 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?viewaspnetcore-2.2Memo其他还有一些上面并未提到比较常用的如 Session如果要上集群的话也应该有相应的分布式 session这个应用没有用到 session所以上面没有提之前用极验验证码的时候有用后来换成腾讯的验证码服务之后去掉了session文件上传如果是存在本地的话也不太合适可能需要存在一个集中的文件服务器或者云端存储如 Azure Blob。。网站里的公告模块的图片上传还没改打算基于 github 或者 开源中国实现一个 storage 其他暂时没想到了想到了再补充吧。Referencehttps://github.com/WeihanLi/ActivityReservationhttps://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?viewaspnetcore-2.2https://en.wikipedia.org/wiki/X-Forwarded-For