SOA: msmq, WCF(Indigo), HelloWorld

PDC 2005 的时候, 又很多专场关于Indigo,现在改为Windows Communication Framework. Indigo能够很好的支持SOA,接下来举一个例子. 把消息队列跟Indigo连接起来.

面向服务的应用体系结构,一定需要一个基础的消息通讯平台. 这个年代 WebService 以其WS-*, 很好的适合了这个应用场景. 在没有Indigo之前,微软的.net 就得用WSE,目前已经是3.0了.

而消息队列,作为一个异步,可靠的消息交换平台,还是又很多自己的用途.

而Indigo呢,事实上Indigo 大大的包含和整合集成了各种通讯协议,基础件,编程模型.

对于一个服务而言, 需要一个Endpoint,需要一个Contract,还需要一个实现.  而 Service 的调用者和提供者之间,则可以通过广泛存在的现有协议进行通讯. 而Indigo 就是把这些东西全部都给你绑定再一个Framework中,换言之以前你要写很多的东西,现在代码极度简化.

就好比以前用API Create 一个稍微pp一点的窗体,现在只要实例化一个类就可以了.

接下来,装了SDK的,可以很快cover一个例子.

我提供了一个最简单的Service, 是HelloWorld Service, 当然Service 只要是自治,有明确的边界,基于Contract.. 你也可以把HelloServie 当作一个订单处理的service.

面向服务,首先要有一个Contract,这个跟SQL 2005中的Service Broker一样

在.net 中,我们可以对类做一些属性标记,系统会自动提取这些Contract,所谓contract包含提供什么功能,需要什么输入输出.

比如我新建一个类. 可是这个类加了一些特殊的属性,可以自动生成类似wsdl一样的contract.

None.gif   [ServiceContract()]
None.gif    
public   interface  IService1
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        [OperationContract(IsOneWay
=true)]
InBlock.gif        
void MyOperation1(string myValue);
ExpandedBlockEnd.gif    }

None.gif
None.gif    
public   class  service1 : IService1
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
public void  MyOperation1(string myValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif           System.IO.StreamWriter sw
= System.IO.File.AppendText("C:\\Demo.txt");
InBlock.gif           sw.WriteLine(DateTime.Now.ToString() 
+ " Received: " + myValue);
InBlock.gif           sw.Close();
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

严格意义上讲, myvalue这个参数应该有个schema来定义,由于是基本的数据类型,可以忽略.

这边加了很多的属性,用来标记contract的内容.

接下来就是需要有一个集成来Host 这些服务. 在Indigo中,默认提供了很多的绑定.当然不同绑定有其使用场景. 比如以前我们用webservice,是基于Soap/xml的,绝大多数是http的通讯. 而remoting可能是tcp或者http, Com+ queued Component则是用msmq. 在indigo中你只要选择一下就可以. 比如我用msmq作为通讯协议,当然msmq是异步的. 我们的服务就无法直接有返回值.
我特意加了一个oneway的属性.
接下来,我选择一种通讯的协议.msmq来Listen
所以代码跟remoting很像,我用一个console来host这个service.
None.gif   internal   class  MyServiceHost
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        
internal static ServiceHost myServiceHost = null;
InBlock.gif
InBlock.gif        
internal static void StartService()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif                       
InBlock.gif            Uri msqAddress 
= new Uri("net.msmq://localhost/private/Indigotest");
InBlock.gif
InBlock.gif
InBlock.gif       
InBlock.gif            myServiceHost 
= new ServiceHost(typeof(service1), msqAddress);
InBlock.gif                    
InBlock.gif            
InBlock.gif
InBlock.gif            myServiceHost.Open();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
internal static void StopService()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// Call StopService from your shutdown logic (i.e. dispose method)
InBlock.gif
            if (myServiceHost.State != CommunicationState.Closed)
InBlock.gif                myServiceHost.Close();
ExpandedSubBlockEnd.gif        }

InBlock.gif
InBlock.gif        
public static void Main()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif             StartService();
InBlock.gif            System.Console.ReadLine();
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

所以这时候我的servie 的endpoint就是net.msmq://localhost/private/Indigotest

当然跟remoting一样,我定义好了contract,我需要配置一下,哪些contract,哪些service是公布出来的所以配置文件也要写一下.不过这都是自动生成的

None.gif <? xml version="1.0" encoding="utf-8"  ?>
None.gif
< configuration >
None.gif
None.gif  
< system .serviceModel >
None.gif    
< services >
None.gif      
< service  type ="WinFXServiceLibrary1.service1" >        
None.gif              
< endpoint  contract ="WinFXServiceLibrary1.IService1"  binding ="netMsmqBinding"     />           
None.gif      
</ service >
None.gif      
None.gif    
</ services >
None.gif  
</ system.serviceModel >
None.gif
</ configuration >

这时候,service就OK了.  为此我在private队列中,加了一个indigotest队列,并且是事务性的.

这时候,我可以用一些sdk的工具,生成客户端的proxy,就跟以前的wsdl.exe,soapsuds.exe 一样,他又一个svcutil.exe 当然我需要一个基本的httpbinding,跟soapsuds一样.

然后比如svcutil.exe http://localhost:8080/demo?wsdl ,这时候会帮你生成一个配置文件一个一个cs.就是proxy.

Proxy 的代码如下
None.gif // ------------------------------------------------------------------------------
None.gif
//  <auto-generated>
None.gif
//      This code was generated by a tool.
None.gif
//      Runtime Version:2.0.50727.42
None.gif
//
None.gif
//      Changes to this file may cause incorrect behavior and will be lost if
None.gif
//      the code is regenerated.
None.gif
//  </auto-generated>
None.gif
// ------------------------------------------------------------------------------
None.gif

None.gif
None.gif
None.gif[System.ServiceModel.ServiceContractAttribute()]
None.gif
public   interface  IService1
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
InBlock.gif    [System.ServiceModel.OperationContractAttribute(Action
="http://tempuri.org/IService1/MyOperation1",IsOneWay=true )]
InBlock.gif    
void MyOperation1(string myValue);
ExpandedBlockEnd.gif}

None.gif
None.gif
public   interface  IService1Channel : IService1, System.ServiceModel.IClientChannel
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
ExpandedBlockEnd.gif}

None.gif
None.gif
public  partial  class  Service1Proxy : System.ServiceModel.ClientBase < IService1 > , IService1
ExpandedBlockStart.gifContractedBlock.gif
dot.gif {
InBlock.gif    
InBlock.gif    
public Service1Proxy()
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
public Service1Proxy(string endpointConfigurationName) : 
InBlock.gif            
base(endpointConfigurationName)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
public Service1Proxy(string endpointConfigurationName, string remoteAddress) : 
InBlock.gif            
base(endpointConfigurationName, remoteAddress)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
public Service1Proxy(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) : 
InBlock.gif            
base(endpointConfigurationName, remoteAddress)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
public Service1Proxy(System.ServiceModel.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : 
InBlock.gif            
base(binding, remoteAddress)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
ExpandedSubBlockEnd.gif    }

InBlock.gif    
InBlock.gif    
public void  MyOperation1(string myValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif          
base.InnerProxy.MyOperation1(myValue);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

None.gif

这个Proxy 其实没有跟service Share Class,而是通过他的Contract 生成了一个代理类.

当然需要有配置文件来配置客户端跟服务端的通讯协议,假设是消息队列,比如重试的机制,可靠传递的机制,要不要事务等.

看一下我的很简单,只是记录了一下我的service 地址
None.gif <? xml version="1.0" encoding="utf-8" ?>
None.gif
< configuration >
None.gif  
< system .serviceModel >
None.gif    
< client >
None.gif      
< endpoint  address ="net.msmq://localhost/private/IndigoTest"  bindingConfiguration ="msmq"
None.gif          binding
="netMsmqBinding"  contract ="IService1"   >
None.gif        
< identity >
None.gif          
< userPrincipalName  value ="montaqueDemo"   />
None.gif        
</ identity >
None.gif      
</ endpoint >
None.gif    
</ client >
None.gif    
< bindings >
None.gif     
None.gif      
< netMsmqBinding >
None.gif        
< binding  name ="msmq" >
None.gif          
< security  mode  ="None" />
None.gif        
</ binding >
None.gif      
</ netMsmqBinding >
None.gif    
</ bindings >
None.gif  
</ system.serviceModel >
None.gif
</ configuration >



然后调用就很简单了

 

None.gif   new  Service1Proxy().MyOperation1( " haha " );

这个时候,一旦Service Down了,会自动发到对应的msmq队列中,online之后自动继续.

没有一句代码访问msmq,可是已经有了msmq的功能.呵呵.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值