クラスタへのスタンドアロンからasp.netコア
イントロ
自分の部屋を予約プロジェクトのこの記事では例として、何をすべきか、分散アプリケーションにスタンドアロンのアプリケーションからのasp.netコアアプリケーションを見てください。
サンプルプロジェクト
部屋のご予約は2つのバージョンが、提供してクラスター・エディション
とスタンドアロン版を
:他の環境とは独立して、スタンドアロンの展開が簡単、データベースはSQLiteのある、詳細な展開ドキュメントは、を参照することがhttps://github.com/WeihanLi/ActivityReservation/blob/dev/docs/deploy/standalone.md
クラスタ・エディションは、現在依存コンポーネントは、MySQL(データベース)/ Redisの(キャッシュ)/ elasticsearch(ログ)を有しています
ジャーナル
ログは、ここでマシン上のファイルを表示するには直接sshをすることができ、ファイルに出力することがスタンドアローンの展開を問題なくすることが判明したが、クラスタログに展開して、ファイルへの出力は、それは少しトラブルが、ログが分散されてトラブルシューティングを行う場合多くのマシン上で、単に問題を解決しないかもしれないマシンのいずれかにログを見てください。
この痛みにログオンすると、私は、elasticsearchにログオン統一ESにログ出力、および検索する/ログkibanaを分析するために移行することができます。
コンポーネントはlog4netのを使用していたログインし、ESへのログ出力を、アペンダのESを書きましたが、その後、より多くのlog4netの使用は十分に柔軟ではないと感じ、その後、部品交換しserilogを記録し、あなたが簡単に拡張することができserilogを使用し、ログを増やしますカスタムserilogのenricherに記録される情報は、参照することができ、レコードを高めるために、情報serilogカスタムenricher
エスもう一つの利点は、検索ログは非常に高速であるということであるログ格納するのに使用し、簡単にkibana統計分析を助けることができます
記事を借りる地図上乗り、次はトップ10最も訪問されたIPアドレスを描画するRequestIPログkibanaに基づいています
キャッシュ
单机部署为了不增加系统复杂度,不引入外部依赖,单机版使用的是 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
其他还有一些上面并未提到,
上記役立つ倍とテスト検証コードの前には言及が(後でコードテンセントに置き換え、ありませんので、あなたは、クラスタ上にある場合は、より一般的には、このようなセッションとして、使用され、それが適切な分散セッションを持っている必要があり、このアプリケーションは、セッションを使用していませんサービスの後に)セッションを削除するには
ファイルのアップロードは、ローカルがある場合、それは非常に適切ではない、Azureブロブなどの集中ファイルサーバやクラウドストレージの存在を必要とするかもしれません。。(アナウンスメントモジュールは、画像をアップロードするサイトはgithubのに基づいて,,,変更またはオープンソース中国のストレージを実装するつもりされていません)
私はそれを追加すると考えられている他の時間を、期待していませんでした。