关于使用wcf架构分布式系统的一点想法
使用iis host wcf,可以很方便的做负载均衡。
利用这个特点,可以在架构的时候把逻辑层,数据层等部分以wcf的形式发布。
并且,对一个大型系统来说,总是有若干不同的模块,这些模块有些使用量大,有些使用量小,对每个模块都以wcf的形式发布,那么我们可以给使用量大的模块多负载几个,而使用量小的则少负载。
但是使用wcf,会带来额外的性能开销。比如非常少用到模块,他本来可以和网站放在一起,那他们是在一个应用程序域里的,但是以wcf形式发布,就分到2个应用程序域里;使用wcf必然要面对序列化,网络通讯等这些方面的新能损失;为了让服务可以同时服务更多的人,这些性能上的损失是必要的,但服务本来服务的人就不多,这个性能上的损失就不必要。
在开发阶段,我们无法确定上线后哪个模块访问度,哪个模块访问少。
即便是可以确定,如果把认为多的以wcf的形式开发,少的以系统内开发。这个时候在一个项目里会有2套不同的开发方式,不统一,意为着开发人员的难度变大。而且随着业务的增长,以前认为是小的部分现在压力也顶不住了,要改成wcf的形式,改动起来也比较大。
但是真正执行的代码其实就是那个类,就是那些代码。
很自然就想到使用一个ioc容器来解决这个问题,在开发时,统一使用wcf的形式。在部署时,先以wcf的形式部署(配置文件都写好),这个时候web是不引用wcf的dll的,只是引用了web服务。如果要把wcf放到和web一个进程中,只要把wcf的dll考到web的bin目录下就可以了。
以下使用autofac作为ioc容器做实验。
建立web项目及wcf项目
把wcf的服务契约提炼到一个新的项目里,这个项目里只有接口,并且这个项目要被web引用。web不引用wcf项目。
在web项目的web.config里写好wcf的调用配置,可以先用vs引用生成。
最后在global里配置autofac
try { var path = AppDomain.CurrentDomain.BaseDirectory; var ass = Assembly.LoadFrom(path + "bin\\WCFHelper.dll"); builder.RegisterAssemblyTypes(ass).AsImplementedInterfaces(); } catch { builder.Register<IMyHelper>(x=>new ChannelFactory<IMyHelper>("IMyEnd").CreateChannel()).OnRelease(x=>((IClientChannel)x).Close()); }
如果本地有dll,则直接注册
如果没有,则需要手动添加所有的服务,并给定配置。
切换是否使用wcf,只需要在web的bin文件夹里存在/不存在 对应的dll