搭建分布式 ASP.NET Core Web

Published on 10/10/2016 11:49:03 AM

单台Web处理用户请求的能力是有限的,因此我们可能会需要搭建分布式的Web服务器。

当前市面上,可能用的比较多的是会话保持,这种模式下,开发者只需将先前开发好的、不支持会话共享的程序部署在多台服务器上,负载均衡提供商会要求开发者设置保持时间,就可以完成部署。但其缺点是仅仅将用户分配到不同节点,不是将请求分配到不同节点,粒度过大,会导致负载不够均衡。

下面我们从各个角度介绍一下如何让你的ASP.NET Core网站系统摆脱会话保持

Session Sharing

分布式Web的第一大棘手问题就是登录状态。ASP.NET Core中默认是将Session ID进行保护的,因此这些数据是被加密过的,并以xml文件形式存在保护区,因此我们要将这个文件共享出来。

因此我们需要实现Session Sharing,对于不同平台,我们有不同的做法(在ASP.NET Core 1.1.0发布前,我们只能通过文件系统进行共享):

Windows

在Windows中,我们使用UNC路径来实现共享。首先建立一个文件夹,在共享中赋予Guest用户读写权限。

file

Linux

Linux中我们需要安装nfs来实现共享,首先选择一个节点,作为nfs服务器(假设IP为10.0.0.254)

apt-get install nfs-kernel-serve

接下来创建一个文件夹:

mkdir /share

下面编辑nfs配置文件,以配置欲共享的路径

vi /etc/exports

在这个配置文件里,我们配置三个参数:路径、IP或IP段、读写权限。每行表示一条记录,可以重复。

/share     10.0.0.1/24(rw,sync,no_subtree_check)
/share     10.0.1.1/24(rw,sync,no_subtree_check)

保存后,重启nfs服务

service nfs-kernel-server restart

至此NFS服务器就部署完毕了,下面在各个节点中挂在nfs共享的文件夹。

安装portmap:

apt-get install portmap nfs-common

在每台节点中创建文件夹,作为挂载路径:

mkdir /share-remote
mount -t nfs 10.0.0.254:/share /share-remote

至此即完成了共享


我们需要为我们的ASP.NET Core程序配置DataProtect,让其将xml文件保存至共享路径中,进入Startup.cs,添加AddDataProtection,并指定路径:

public void ConfigureServices(IServiceCollection services)
{
#if WINDOWS
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"\\10.0.0.254\share"));
#elif LINUX
    services.AddDataProtection()
        .PersistKeysToFileSystem(new DirectoryInfo(@"/share-remote"));
#elif REDIS_ON_NET_CORE_1_1_0 // ASP.NET Core 1.1.0 新增将Session ID存储至Redis中
    var redis = ConnectionMultiplexer.Connect("10.0.0.254"); 
    serviceCollection.AddDataProtection()
        .PersistKeysToRedis(redis, "DATA_PROTECTION_KEYS_");
#endif
}

DataProtect配置过后,需要配置分布式缓存:

services.AddDistributedRedisCache(x => 
{
    x.InstanceName = "SESSION_INSTANCE_";
    x.Configuration = "10.0.0.254"; // StackExchange.Redis Connection String
});
services.AddSession(x =>
{
    x.IdleTimeout = new TimeSpan(1, 0, 0);
});

配置好分布式缓存后,session就已经可以share了,包括使用了Identity的网站也同时受益,摆脱了对会话保持的依赖。

SignalR Scale Out

如果网站使用了SignalR,那么需要将SignalR消息推送到各个节点,就需要使用Redis来Scale out SignalR:

进入project.json来添加Pomelo.AspNetCore.SignalR.Redis包,版本为0.1.0

ConfigureServices中添加下面的代码

services.AddRedis(x =>
{
    x.ConnectionString = "10.0.0.254"; // StackExchange.Redis Connection String
    x.Database = 0;
    x.EventKey = "SIGNALR_INSTANCE";
})
.AddSignalR(options =>
{
    options.Hubs.EnableDetailedErrors = true;
});

现在SignalR的消息就在各个节点中互通了。

分享到:

Comments

使用微信扫码