博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
code4fun:host wcf service just in time
阅读量:5349 次
发布时间:2019-06-15

本文共 5478 字,大约阅读时间需要 18 分钟。

当ServiceContract非常多的情况下,比如要self-host hundred of service的时候,or更多的时候,每次hosting都是建立一个tcp listen.这样,host的init工作会占用非常多的时间和资源。对于一些对start有较快需求的case,这明显会影响用户体验。本文意在寻求一种技术手段解决这个问题,让service只有在运行时才host。我们姑且称之为host just in time吧

先说一下思路。

client如果能发送消息给service,并且消息可达,先决条件就是消息到达service之前,service已经被host,注意,是说消息到达之前,而并不是在客户端发送消息之后,这就给我们提供了一个可以做手脚的时期,即消息从客户端发送出去到消息在被服务端接收之前这段时间,如果我们能Inspect它,并根据其self description,便能在消息发送到真正的服务之前,host那个service,而做这样一个事情,rounter明显是最在行的了。下面是实现host just in time的原理图。

按照上面的思路,做了一个简单的demo,过程如下

首先创建Contracts项目Jillzhang.Wcf.HostJIT.Contracts,包含两个ServiceContract:ICalculator和IActivity,代码分别为:

ICalculator:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ServiceModel;namespace Jillzhang.Wcf.HostJIT.Contracts{[ServiceContract]public interface  ICalculator{[OperationContract]int Add(int a, int b);}}

IActivity:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ServiceModel;namespace Jillzhang.Wcf.HostJIT.Contracts{[ServiceContract]public interface IActivity{[OperationContract]void Excute();}}

demo只模拟对这两个ServiceContract的host just in time

建立好契约项目之后,新建服务项目:Jillzhang.Wcf.HostJIT.Services,添加两个类:Caculator和Activity,分别实现ICalculator和IActivity,其代码如下:

Caculator:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using Jillzhang.Wcf.HostJIT.Contracts;namespace Jillzhang.Wcf.HostJIT.Services{public class Calculator : ICalculator{public int Add(int a, int b){return a + b;}}}

Activity:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using Jillzhang.Wcf.HostJIT.Contracts;namespace Jillzhang.Wcf.HostJIT.Services{public class Activity:IActivity{public void Excute(){Console.WriteLine("activity is running!");}}}

接着,我们需要简历本实例中最重要的项目:Jillzhang.Wcf.HostJIT.Dispatcher,这个项目的release自身就是一个对wcf service的self-host的hosting app.为了实现路由,截获以及调度的功能,实现了路由接口IRounter和类Dispatcher,下面是他们的code:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ServiceModel;using System.ServiceModel.Channels;using System.Collections;using Jillzhang.Wcf.HostJIT.Services;namespace Jillzhang.Wcf.HostJIT.Dispatcher{[ServiceContract]public interface IRounter{[OperationContract(Action = "*", ReplyAction = "*")]Message ProcessMessage(Message msg);}[ServiceBehavior(AddressFilterMode = AddressFilterMode.Any)]public class Dispatcher : IRounter{public static readonly Hashtable hostTable = new Hashtable();public Message ProcessMessage(Message msg){string to = msg.Headers.To.ToString();string serviceName = "";//todo:if no host,host firstif (to.IndexOf("8031") > -1){if (!hostTable.ContainsKey("Calculator")){ServiceHost host = new ServiceHost(typeof(Calculator));host.Opened += new EventHandler(delegate(object sender, EventArgs arg){Console.WriteLine("Calculator service is opened!");});host.Open();hostTable.Add("Calculator", host);}serviceName = "Calculator";}else{if (!hostTable.ContainsKey("Activity")){ServiceHost host = new ServiceHost(typeof(Activity));host.Opened += new EventHandler(delegate(object sender, EventArgs arg){Console.WriteLine("activity service is opened!");});host.Open();hostTable.Add("Activity", host);}serviceName = "Activity";}//todo:rounter the messageusing (ChannelFactory
channelFactory = new ChannelFactory
(serviceName)){var chanenl = channelFactory.CreateChannel();using (chanenl as IDisposable){return chanenl.ProcessMessage(msg);}}}}}

通过代码可以看出,首先Dispatcher是一个有路由功能的服务,它会根据message中Header中的To判断要调用的Service是哪一个,然后判断是否已经承载了那个最终目的的Service,如果没有,host frist and add it to hostTable ,host之后,就可以将消息调度给真正的服务了。

app.config的代码如下:

而在这个项目中,我们开始只需要host IRounter契约。host代码为:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ServiceModel;namespace Jillzhang.Wcf.HostJIT.Dispatcher{class Program{static void Main(string[] args){using (ServiceHost host = new ServiceHost(typeof(Dispatcher))){host.Opened += new EventHandler(delegate(object sender, EventArgs arg){Console.WriteLine("dispatcher service is opened!");});host.Open();Console.Read();}}}}

建立客户端程序Jillzhang.Wcf.HostJIT.Client,并且将app.config更改为:

Programe.cs为:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ServiceModel;using Jillzhang.Wcf.HostJIT.Contracts;namespace Jillzhang.Wcf.HostJIT.Client{class Program{static void Main(string[] args){Console.WriteLine("press any key when dispatcher service is ok!");Console.Read();CallCalculator();CallActivity();CallCalculator();CallActivity();Console.ReadKey(true);}static void CallCalculator(){using (ChannelFactory
channelFactory = new ChannelFactory
("Calculator")){var channel = channelFactory.CreateChannel();using (channel as IDisposable){Console.WriteLine(channel.Add(1, 2).ToString());}}}static void CallActivity(){using (ChannelFactory
channelFactory2 = new ChannelFactory
("Activity")){var channel = channelFactory2.CreateChannel();using (channel as IDisposable){channel.Excute();}}}}}
 
 
 
服务端:
 
最终验证效果和原来想象中一致。OK!
demo项目:

转载于:https://www.cnblogs.com/jillzhang/archive/2008/10/27/1320086.html

你可能感兴趣的文章
OpenCV的配置
查看>>
spring Cache + Redis 开发数据字典以及自定义标签
查看>>
成功连上数据库顿感世界美好许多
查看>>
编程注意2
查看>>
《C++ Primer Plus》第12章 类和动态内存分配 学习笔记
查看>>
javascript中sort()排序方法总结
查看>>
实现聊天界面的代码
查看>>
自己生成一个NDK的浅析
查看>>
Excel数据导入到数据库
查看>>
jQuery最佳实践
查看>>
SELinux FAQ
查看>>
Java中synchronized同步的理解
查看>>
python 数值计算库
查看>>
java 服务重启 js 中被注释代码仍然执行
查看>>
我并不是不闻不问![C#]
查看>>
web前端经典小题
查看>>
AutoCAD如何倒角 倒圆角 倒直角
查看>>
Office PPT中如何插入flash
查看>>
C# Fade Form Effect With the AnimateWindow API Function
查看>>
golang多维数组的切片
查看>>