负载均衡下的资源文件配置/多站点下的资源文件夹共享(Windows IIS)

前言:

负载均衡用的是NLB,微软的方案不太靠谱,举个例子吧,AB两台服务器负载出C,如果用户访问访问C之后分配的是A,那么如果A挂了,是不会自动切换到B的。据说后来还有一种NLB的方案可以实现,也不想再试了。

背景:

这里主要是以图片资源为主,以下是可能存在的场景:

1、同一台服务器上,部署了多个与业务相关的站点,同样要用到统一的图片资源(比如接口和后台这两个业务系统,后台上传了图片,接口必须能获取到这些图片数据,同样,反过来也是一样)

2、使用了负载均衡(这里是微软的NLB方案(强烈不建议使用微软的方案),同样也有很多负载均衡方案,比如nginx等),多个站点同时有图片操作,那么最后每个站点都要同步进行显示。

3、上面两点都是基于Web的方案,那么如果出现WinForm这种,我需要保存文件到一个共享文件夹时的场景。

具体操作:

1、针对上面第1点,对应的解决方案是在IIS新建虚拟目录实现,且新建的虚拟目录在代码操作上和真实目录一致。

效果类似如下:

实质上,上面web1中的upload是真实存在的文件夹,而web2上是虚拟目录,但是最终出来的效果都是一样的,操作如下:

这里可以指向本机文件夹,也可以是局域网共享的文件夹,如果是需要账号密码的文件夹,可以设置【连接为(C)...】配置。不过一般我们只要本机就够了。

接下来我们来代码操作一下:web1上上传了图片,试下web2访问一下,然后web2上传了图片,试下web1的访问。注意:我这里直接使用一套代码部署两个站点,然后看下是否能达到操作虚拟目录时,代码是一致的。

前台:

后台代码:

操作1:先部署到web1上,这个站点是有真实文件夹Upload的,完成通过。

操作2:部署到web2上,这个站点没有真实文件夹Upload的,还是上面那份代码:

一切正常!

2、针对上面第2点,那么就要配置同一个内网的文件夹共享。但是代码还是上面的一份,只不过web.config上需要配置共享账号。

具体操作:

1)在A服务器添加User1的账号,密码为123456;同时也在B服务器添加User1的账号,密码为123456;注意,这里两台服务器上的账号密码都是一致的

2)配置A服务器上的Upload文件夹为共享,并添加User1用户进入共享权限

并添加安全的用户User1的权限

重要一步,在A服务器和B服务器上设置这个文件夹的权限:“C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files”的权限

经过测试,如果不加这一步,会出现编译不通过的问题。

3)在A服务器和B服务器上新建web站点,其中A服务器上的Upload文件夹为真实文件夹,但是B服务器上的Upload文件夹为虚拟文件夹,并指向A服务器的Upload共享文件夹

4)在代码上,需要配置web.config,添加账户模拟设置

<system.web>
    <identity impersonate="true" userName="User1" password="123456"/>
</system.web>

5)进行部署并测试,先部署A服务器,看运行效果

 

成功,有文件存在。

再来部署B服务器,看运行效果

可以看出,也是成功的上传的

上图中的10.18.66.101为A服务器的内网IP

3、针对上面第3点进行测试,那么就要用到在程序中模拟域帐户进行登录操作,这种方式同时也是兼容Web方案的,只不过Web方案本身提供更优的解

代码实现:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;

namespace ConsoleApplication_Test
{
    internal static class WinLogonHelper
    {
        /// <summary>
        /// 模拟windows登录域
        /// </summary>
        [DllImport("advapi32.DLL", SetLastError = true)]
        public static extern int LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
    }

    class Program
    {
        static void Main(string[] args)
        {
            IntPtr admin_token = default(IntPtr);
            WindowsIdentity wid_admin = null;
            WindowsImpersonationContext wic = null;

            //在程序中模拟域帐户登录
            if (WinLogonHelper.LogonUser("User1", "10.18.66.101", "123456", 9, 0, ref admin_token) != 0)
            {
                using (wid_admin = new WindowsIdentity(admin_token))
                {
                    using (wic = wid_admin.Impersonate())
                    {
                        System.IO.File.Create(@"\\10.18.66.101\Upload\test.txt");
                    }
                }
            }
        }
    }
}

 

 这里还是用User1账号,密码123456的用户去登录10.18.66.101这台机器,实质上是用模拟域登录。

登录完之后,然后就进行文件操作,记得,这个操作也像我们操作共享文件一样,带上IP这些。如“\\10.18.66.101\Upload\test.txt”,小技巧,前面加了@符号。

测试效果

将控制台部署到B服务器

效果也是成功的。

总结:

0、模拟域帐户之后,就有了模拟用户的权限,这里千万要注意安全!

1、通过Web方案和WinForm方案,都可以实现局域网内的文件来回交换。

2、假设A服务器在杭州,B服务器在北京,那么要组建内网,可以直接用VPN方案,Windows下搭建PPTP,这里我提供阿里云的的搭建方案:http://www.cnblogs.com/EasonJim/p/5361943.html

3、还有一种第三方的方案,购买又拍云这类型的cdn方案,提供统一的接口和访问地址,那么完全解决,都是多个程序统一一个路径进行上传的思路。

4、如果用了负载均衡的方案,在程序上如果用了Session的也要做相应的处理,比如StateServer方案。

5、极力反对使用微软的NLB方案

参考:

http://www.cnblogs.com/yukaizhao/archive/2010/06/12/c-sharp-windowsimpersonationcontext.html

http://www.cnblogs.com/dudu/archive/2012/03/27/asp_net_share_folder.html

测试代码:

https://github.com/easonjim/1_dotnet_example/tree/master/%E8%B5%84%E6%BA%90%E6%96%87%E4%BB%B6%E5%85%B1%E4%BA%AB/WebApplication_Test

后话:

这篇文章是我在13年给一家摩托车公司做抽奖的时候涉及到的配置,当时网络上对于这类配置比较少,且都是不太可行的,由于用的是微软的NLB负载均衡方案,所以在项目实施上效果也非常不理想。

posted @ 2016-12-07 13:31  EasonJim  阅读(3541)  评论(1编辑  收藏  举报