appfabric cache里,有主要主机(leadhost)这个概念。
在一些情况下,主要主机挂了,整个cache集群就挂了。
一、使用xml配置。
如果有2台leadhost,挂一个,全挂
如果有3台leadhost,可以挂一个,挂两个全挂。
http://msdn.microsoft.com/zh-cn/library/ee790895.aspx
“例如,设想下图中显示的六服务器缓存群集。在此示例中,主要主机执行群集管理角色,并将两个缓存主机指定为主要主机。
如果群集中的任一普通缓存主机出现故障,此群集可能会一直运行。非主要主机上的数据会丢失(假定未启用高可用性),但群集的其余部分会继续提供服务并存储数据。实际上,即使未指定为主要主机的四个缓存主机全部失去,群集仍可以保持运行。
只要其中一个主要主机出现故障,整个缓存群集就会关闭,因为不再是大多数主要主机在运行。若要减少此问题,您可以选择指定其他主要主机。”
以上是ms文档中的说明
二、使用sqlserver配置
工作组不允许使用sqlserver配置,只有域才可以。
每台cache服务器上的appfabric cache服务,都得用域用户启动(如果sqlserver和cache在同一台,这台貌似可以不用)
导出配置文件,修改,导入
http://msdn.microsoft.com/zh-cn/library/ee790910.aspx
“找到并编辑 partitionStoreConnectionSettings 元素中的 leadHostManagement 属性,该元素为 advancedProperties 元素的子元素。将其设置为 true 意味着被指定为主要主机的缓存主机将执行群集管理角色。将其设置为 false 意味着存储群集配置数据库的 SQL Server 的实例将执行群集管理角色。”
“当 SQL Server 执行群集管理角色时
如果群集的 leadHostManagement 设置为 false,则无论 leadHost 设置如何,每个缓存主机仅承担与缓存数据相关的非主要主机的普通责任。在这种情况下,用于存储群集配置设置的 SQL Server 实例还用于执行群集管理角色。
如果发生服务器故障时
在 SQL Server 执行群集管理角色时,为了使群集保持可用,一个或多个缓存主机必须能够访问 SQL Server 数据库。
例如,设想下图中显示的六服务器缓存群集。
在此示例中,SQL Server 执行群集管理角色,所有六个缓存主机可以将其资源专用于缓存客户端的数据访问。
如果群集中的任何一个缓存主机发生故障,则这些服务器上的数据都会丢失(假定未启用高可用性),但群集会继续运行。其他缓存主机上的数据会继续提供给缓存客户端。事实上,在这种情况下,如果群集丢失了六个缓存主机中的五个,它仍可以继续工作。”
按照这种设置方式,不论那台cache down了,都不影响(全down自然不行),只要sql server不down。
ps:我在使用sql server 2008 r2 express做测试的时候,我的sql实例是sqlexpress。
在与sql同一台的机器上,设置sql连接时,使用.\sqlexpress设置
而在别的机器上设置sql连接时,使用ip\sqlexpress,机器名\sqlexpress都提示远程连接有问题,为这个远程连接整死了。
最后发现不需要输入sql实例名只要输入ip即可,不解
我没有使用文档中提供的命令形式,只是图形界面操作的
三、客户端
1、在host中把上面设置好的host都加进去,这样有一个down了也没关系
2、网上一些教程说需要引用2个dll,但其实是4个。如果是vs里引用的,他会自动把另外那两个引进去,但是如果是自己手动copy,就要注意多copy两个
Microsoft.ApplicationServer.Caching.Client.dll
Microsoft.ApplicationServer.Caching.Core.dll
Microsoft.WindowsFabric.Common.dll
Microsoft.WindowsFabric.Data.Common.dll
以上4个dll,在appfabric的安装目录下可以找到
服务器是08 r2,x64的,开发机是x86的,我没有测试拿x64的dll在x86的机器上开发会怎样,估计是会有问题。我直接找到x86的dll开发,放到服务器上时,再替换成x64的。
接上一篇
经过进一步测试发现
db.Orders.MergeOption = System.Data.Objects.MergeOption.NoTracking;
orderlist = db.Orders.ToList();
查出来的东西,虽然状态也是Deteached,但是导航属性不是null手动Deteach之后
db.ObjectStateManager.ChangeObjectState(item, System.Data.EntityState.Detached);或 db.Detach(item);
注意,第二种方法如果已经是Deteached状态会报错
导航属性会为null
但是如果查询的时候已经加了NoTracking,是不行的
比如,在数据层,通过NoTracking方式取得了一些数据
在逻辑层,需要放入cache。
则需要建立一个新的ObejctContext先attach,再deteach,才能保证他的导航属性为null。
导航属性为null,才能顺利的放入cache。
为了在notracking下,导航属性为null,必须明确指定lazyload=false
这算不算是ef的bug呢,同样都是deteached,但是状态却还有不同。
首先是表结构,一个一对多的关系,和一个单独的表来做测试
1: var db = new TestDBEntities();2: var obj1 = db.tab1.FirstOrDefault();3: var list1 = db.tab1.ToList();4:5: var user1 = db.Users.FirstOrDefault();6: var userlist = db.Users.ToList();7:8: var order1 = db.Orders.FirstOrDefault();9: var orderlist = db.Orders.ToList();10:11:12: cache.Put("obj1", obj1);13: Console.WriteLine("单独表个体");14: cache.Put("list1", list1);15: Console.WriteLine("单独表list");16:17: cache.Put("user1", user1);18: Console.WriteLine("user表个体");19: cache.Put("userlist", userlist);20: Console.WriteLine("user表list");21:22: cache.Put("order1", order1);23: Console.WriteLine("order表个体");24: cache.Put("orderlist", orderlist);25: Console.WriteLine("order表list");
查出来,放入cache,貌似没什么问题
但是如果用下面的写法
1: tab1 obj1;2: List<tab1> list1;3: Users user1;4: List<Users> userlist;5: Orders order1;6: List<Orders> orderlist;7: using (var db = new TestDBEntities())8: {9: db.tab1.MergeOption = System.Data.Objects.MergeOption.NoTracking;10: db.Users.MergeOption = System.Data.Objects.MergeOption.NoTracking;11: db.Orders.MergeOption = System.Data.Objects.MergeOption.NoTracking;12: obj1 = db.tab1.FirstOrDefault();13: list1 = db.tab1.ToList();14: user1 = db.Users.FirstOrDefault();15: userlist = db.Users.ToList();16: order1 = db.Orders.FirstOrDefault();17: orderlist = db.Orders.ToList();18: }19:20: cache.Put("obj1", obj1);21: Console.WriteLine("单独表个体");22: cache.Put("list1", list1);23: Console.WriteLine("单独表list");24:25: cache.Put("user1", user1);26: Console.WriteLine("user表个体");27: cache.Put("userlist", userlist);28: Console.WriteLine("user表list");29:30: cache.Put("order1", order1);31: Console.WriteLine("order表个体");32: cache.Put("orderlist", orderlist);33: Console.WriteLine("order表list");
两种写法的区别在于
1、使用了using,关闭数据连接
2、使用了notracking,或者使用
order1 = db.CreateObjectSet<Orders>().FirstOrDefault();
这种泛型形式
Orders关联的Users是唯一的。此时,会报这个错误。
注意,只有在一对多关系的多方放入缓存时,他要获取一那方的数据时会出错
一方放入,对应多方是集合,不会报错
猜测:大概是在序列化的时候会进行访问
目前未找到什么通过配置cache能解决的方法。
using,notracking,或泛型形式,都是在分层下经常使用的。
最让我无语的是,同样的东西放到memcache里一点事都没有。真shit。
参考memcache client,是做了二进制序列化,自己进行而进制序列化也不会有问题,不知道appfabric采用的是什么形式。
已找到问题的原因,请看
两台服务器,都安装appfabric,作为缓存服务器
其中一台做cluster,另一个join
做cluster的机器选择xml配置文件路径时,选择本机的一个共享目录
join的机器做配置时,选择的xml路径要选择第一台cluster机器的那个共享目录
第三台机器做web
在3台机器上建立同名,名密码的用户
给cluster grant此用户
在web服务的iis里,进程池用户改为此用户,对iis6,需要把此用户加入iis_wam组
相关web.config
<section name="dataCacheClient" type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
<dataCacheClient> <hosts> <host name="192.168.0.123" cachePort="22233" /> </hosts> </dataCacheClient> 可能需要加入
<identity impersonate="true" userName="username" password="passwd" />
此3台机器并不是域。
很奇怪的是,我使用默认的network service账户,并且给cache授权此账户竟然不行,但是自己建立一个账户就可以了,不解为什么。
获取80端口的连接数一定要大
ajax comet设置超时比如30秒
真正的2个网站的超时,默认120秒
farm的默认超时30秒,要改此超时时间,大于网站超时时间(proxy里)
否则网站没超时,farm超时了,farm会认为网站unhealthy
不管怎么样,总算是配上了。
首先需要一个80端口的网站,已获取80的访问请求,此网站可以没有内容,但是一定要有这个网站,此网站的连接数,限制了farm的连接数
使用其他端口如81,建立真正的网站
建立farm,加入127.0.0.1:81的网站
修改自动生成的转发规则
在条件中加入,{SERVER_PORT}匹配80。
这样,对80的请求会路由到farm,而farm转向到本机的81不会进入farm。
理论上,可以在一台机器,多个端口,只拿一个端口做farm其他的做web server。但是可惜不行,再次添加127.0.0.1:82的时候,他认为已有同名服务器了。
不过可以不用127.0.0.1,用localhost啦,局域网IP 192.168.xxx.xxx啦,127.0.0.2啦,总之名字不重复即可。
这样在开发时,有一台机器就可以测试负载均衡的情况了。




