六、在IIS中寄宿MSMQ绑定的WCF服务实现分布式部署 16
- 创建消息队列
-
创建一个非事物性的私有队列
右键选择计算机/这台电脑——管理——服务和应用程序——消息队列——专用队列——新建——专用队列,输入队列的名称,不要勾选事物性队列,即可完成创建非事物性私有队列。
创建非事物性私有队列
-
设置消息队列访问权限
完成创建队列以后,必须设置队列的访问权限,否则无法通过队列发送接收消息。右键选择队列属性——安全选项卡,将everyone和anonymous权限设置为完全控制。如下图所示:
Everyone完全控制
Anonymous完全控制
- 创建WCF服务并绑定消息队列
-
创建HelloService服务
在VS中创建一个解决方案,并且新建一个类库项目,两个控制台项目上图所示。
在WCFMSMQDemo.Service服务层中创建一个名为IHelloService的接口作为服务契约,创建一个名为HelloClient的实现IHelloService接口的类作为服务类。在服务契约中定义一个无返回值的单项访问的方法。消息队列支持无返回值的单向访问。具体代码如下:
[ServiceContract]
public interface IHelloService
{
/// <summary>
///发送消息的方法
/// </summary>
/// <param name="message"></param>
[OperationContract(IsOneWay = true)]
void SendMessage(string message);
}
设置方法的属性IsOneWay=true,返回值为void
服务端代码如下所示:
public class HelloClient:IHelloService
{
public void SendMessage(string message)
{
Console.WriteLine("接收到来自客户端的消息" + message);
}
}
-
设置WCF服务的配置文件
完成契约定义和服务实现以后就可以配置服务端,在Server中添加对Service项目的引用,并添加引用System.ServiceModel,编译生成一下整个解决方案,否则在配置服务端配置文件的时候无法出现智能提示。基于消息队列绑定的WCF服务需要使用net.msmq协议绑定,服务的地址设置为如下格式net.msmq://消息队列所在服务器ip/{private}/队列名称。如果是私有队列必须加上private,公共队列则无需加上。由于我们创建的是私有队列所以服务的地址为net.msmq://localhost/private/myqueue。由于是非事物性队列所以需要这是绑定属性exactlyOnce="false"。这里我们的WCF服务只是用来演示如何调用消息队列就不再设置安全验证模式,直接设置不采用任何安全验证方式<security mode="None" />
具体设置代码如下所示:
<system.serviceModel>
<services>
<service name="WCFMSMQDemo.Service.HelloClient">
<endpoint address="net.msmq://192.168.103.66/private/myqueue" bindingConfiguration="NoneSecurity" binding="netMsmqBinding" contract="WCFMSMQDemo.Service.IHelloService">
</endpoint>
</service>
</services>
<bindings>
<netMsmqBinding>
<binding name="NoneSecurity" exactlyOnce="false" queueTransferProtocol="Native">
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
设置完服务端配置文件以后需要设置一下客户端的配置文件,客户端配置文件与普通的WCF服务端配置稍有不同,具体配置如下:
<system.serviceModel>
<client>
<endpoint address="net.msmq://localhost/private/myqueue" binding="netMsmqBinding" bindingConfiguration="NoneSecurity" contract="WCFMSMQDemo.Service.IHelloService" name="msmqService">
</endpoint>
</client>
<bindings>
<netMsmqBinding>
<binding name="NoneSecurity" exactlyOnce="false" queueTransferProtocol="Native">
<security mode="None" />
</binding>
</netMsmqBinding>
</bindings>
</system.serviceModel>
-
WCF服务服务端和客户端代码实现
using (ServiceHost host = new ServiceHost(typeof(HelloClient)))
{
host.Open();
Console.WriteLine("WCF 服务已经启动@" + DateTime.Now);
Console.ReadKey();
}
服务端代码
using (ChannelFactory<IHelloService> channelFactory = new ChannelFactory<IHelloService>("msmqService"))
{
IHelloService proxyeService = channelFactory.CreateChannel();
proxyeService.SendMessage("Hello World");
Console.WriteLine("调用服务成功");
Console.ReadKey();
}
客户端实现代码
最后启动服务端和客户端后运行结果如下:
-
测试WCF服务
修改客户端代码实现,模拟并发1000次访问,客户端实现代码如下:
using (ChannelFactory<IHelloService> channelFactory = new ChannelFactory<IHelloService>("msmqService"))
{
IHelloService proxyeService = channelFactory.CreateChannel();
Parallel.For(0, 1000, i =>
{
proxyeService.SendMessage("Hello World" + i);
Console.WriteLine("调用服务端" + i);
});
Console.WriteLine("调用成功");
Console.ReadKey();
}
启动服务端,然后启动客户端,运行结果如下
客户端请求结果,模拟并发1000次访问只用了407毫秒
服务端请求结果
- 启用远程访问MSMQ
- 在远程服务器上创建消息队列,具体步骤参见前面
-
设置MSMQ身份验证
右键选择计算机——管理——服务和应用程序——消息队列——属性——服务器安全性——取消勾选"禁用未经身份验证的RPC调用",否则无法通过消息队列收发消息。
Windows 7 上消息队列属性设置
如果是在windows server2008 r2服务器系统上设置会有所不同
Windows server 2008 r2 上消息队列设置
-
修改服务端和客户端消息队列地址绑定。
将地址中的修改为消息队列上服务器上对应的消息队列地址。net.msmq://192.168.103.66/private/myqueue。远程服务器上必须存在消息队列,否则会提示无法打开指定的消息队列。修改后的绑定地址如下
<system.serviceModel><services>
<service
name="WCFMSMQIISDemo.Service.HelloClient"
behaviorConfiguration="HttpGetEnable"><endpoint
address="net.msmq://192.168.103.66/private/HelloService.svc"
binding="netMsmqBinding"
bindingConfiguration="NoneSecurity"
contract="WCFMSMQIISDemo.Service.IHelloService"></endpoint>
<endpoint
address="mex"
binding ="mexHttpBinding"
contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<netMsmqBinding>
<binding
name="NoneSecurity"
exactlyOnce="false"
queueTransferProtocol="Native"><security
mode="None" /></binding>
</netMsmqBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior
name="HttpGetEnable"><serviceMetadata
httpGetEnabled="true"/><serviceDebug
includeExceptionDetailInFaults="true"/></behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true"></serviceHostingEnvironment>
</system.serviceModel>
运行服务端和客户端后结果如下
-
通过消息队列离线使用WCF服务
使用消息队列收发消息,如果客户端与服务端无法及时通信,那么客户端发送的请求消息会暂时保存在本机的消息队列中,前提是本机中安装了消息队列服务,否则无法实现离线调用功能。当客户端能够与服务端正常通信以后,客户端上的消息会被自动发送到服务端的消息队列中然后被服务端处理掉。下面演示一下离线使用WCF服务
首先将客户端和服务端绑定的消息队列地址改为远程服务器上的地址net.msmq://192.168.103.66/private/myqueue,禁用本地网卡,然后启动客户端
客户端功能仍然能使用,我们再看看本地消息队列中是否有数据
可以看到本地传出队列中有一条消息指向远程服务器上的消息队列。现在启用网卡再看看本地消息队列——传出队列和远程服务器消息队列专用队列各有什么变化。
刷新一下,本地消息队列中的传出队列中已经没有消息了,再看一下远程服务器上专用队列中是否有消息
远程服务器上队列中已经有消息了,并且消息ID和本地传出队列中保存过的消息的消息ID一致,证明是同一条消息经过本地传递到了远程服务器上。最后运行一下服务端看能否正确处理消息。
服务端成功处理了客户端离线发送的消息。
-
在IIS中寄宿MSMQ绑定的WCF服务实现分布式部署
通过sefhost虽然也能实现WCF服务的托管但是部署上还是有很多的局限性,那么基于MSMQ消息队列的WCF服务是否能在IIS中托管呢,答案是肯定的。通过微软的进程激活服务(WAS)即可实现非Http绑定的WCF在IIS中托管。要实现非Http绑定的WCF服务在IIS中托管需要做以下步骤的修改。
-
启用WCF的非htttp激活
右键选择开始菜单——控制面板——程序和功能——打开或关闭windows功能,找到.net framwork3.5.1 启用以下功能
Windows 7下实现
Windows server 2008 r2 服务器上
Windows 8/8.1需要安装.net3.5 并勾选windows communication foundation 非http激活和.net4.5中的wcf服务下的消息队列(MSMQ)激活。
-
创建IIS中托管的WCF服务
首先创建一个名为HelloService.svc的私有非事物性队列,并设置队列可以远程访问。然后创建WCF服务。创建WCF服务具体服务定义如下
public
class
HelloClient : IHelloService{
public
void SendMessage(string message){
File.WriteAllText(@"D:\test.txt", message, Encoding.Default);
}
}
设置为msmq绑定,同时开启元素数据获取。具体服务端配置文件如下
<system.serviceModel>
<services>
<service
name="WCFMSMQIISDemo.Service.HelloClient"
behaviorConfiguration="HttpGetEnable"><endpoint
address="net.msmq://192.168.103.66/private/HelloService.svc"
binding="netMsmqBinding"
bindingConfiguration="NoneSecurity"
contract="WCFMSMQIISDemo.Service.IHelloService"></endpoint>
<endpoint
address="mex"
binding ="mexHttpBinding"
contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<netMsmqBinding>
<binding
name="NoneSecurity"
exactlyOnce="false"
queueTransferProtocol="Native"><security
mode="None" /></binding>
</netMsmqBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior
name="HttpGetEnable"><serviceMetadata
httpGetEnabled="true"/><serviceDebug
includeExceptionDetailInFaults="true"/></behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
-
创建网站并添加msmq绑定
完成服务端代码实现以后,即可在IIS中创建网站并添加msmq绑定来实现服务的寄宿。在IIS中新建一个网站,并将网站目录指向创建的WCF所在目录。添加网站的msmq绑定,右键网站——编辑绑定——添加,类型选择net.msmq,绑定信息填写消息队列服务器所在地址,如192.168.103.66。
点击添加按钮添加msmq绑定
默认是http绑定
将添加类型改为net.msmq,绑定信息填写消息队列所在服务器ip
添加net.msmq绑定以后还要增加网站的net.msmq支持,右键网站——管理网站——高级设置——已启用的协议中添加net.msmq
设置完成以后即可启动网站,访问网站下的HelloService.svc文件,如http://localhost:8080/HelloService.svc
启动wcftestclient,添加服务引用
查看D盘根目录下文件
有内容写入,证明服务运行成功。
-
写在最后
如果你对本文有什么不明白的地方可以与我联系,或者有更好的建议与意见欢迎与我交流。QQ:489505067