前言:
负载均衡用的是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>
{
/// <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负载均衡方案,所以在项目实施上效果也非常不理想。
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com