WCF学习总结(五)

Wcf消息交换模式

1.       请求/回复(Request/Reply)

(1)       默认的消息交换模式

(2)       图例:

2.       单向(One-way)

(1)       使用OperationContractAttribute将操作标记为one-way

(2)       没有回应(response),不会报告异常

(3)       客户端虽然不关心消息响应,但是有些情况下希望保证消息能够确实送达:可靠性消息提供暂时性的可靠性,Microsoft® Message Queuing (MSMQ) 能够提供可持久的可靠性

(4)       如果服务器端信道发生了错误,客户端只有在下次调用时才能发现这个错误

(5)       主要应用场景:日志活动或者事件发布

(6)       被设置为单向操作的方法不能包含返回值,即它的返回值只能为void,否则会抛出InvalidOperationException异常

(7)       图例:

3.       双向(Duplex)

(1)       操作可以是request/reply类型或者one-way类型

(2)       回调契约无须标记ServiceContract特性,但是在回调契约中必须为服务的操作标记OperationContract特性

(3)       服务对回调的调用可能会产生死锁。例如,当客户端执行服务操作时,向客户端发出的调用会阻塞服务端进程,以等待服务操作执行完毕。而在该服务操作中,又获得了回调契约对象的引用(或者获得保存的回调契约副本),并执行回调操作。由于服务类被配置为单线程访问,则服务实例是与锁相关联的。如果回调对象也需要返回同一个锁的所有权,简单的说,就是指当回调的应答消息也需要获得与服务实例关联的相同的锁时,就会导致死锁。因为此时服务线程已经被阻塞,服务操作正在等待回调操作执行完毕,而回调操作却又在等待服务释放锁,自然会产生锁的争用。解决死锁的三种方式:一个是将服务配置为允许多线程访问,但这会增加服务开发者管理多线程的负担。第二个方案是将回调设置为重入(Reentrancy),所谓“重入”,是指对同步域拥有独占访问权的线程A调用了同步域之外对象的方法,此时,另外的线程B若要访问该同步域,则线程A将释放对同步域的锁,允许线程B进入。直到线程B执行完毕并释放对同步域的锁后,线程A将重新进入该同步域。配置回调为重入时,因为服务对象是与线程关联的,属于同步域的对象,而回调对象则属于同步域之外的对象。由于服务被配置为重入,则服务调用回调引用时会释放锁。然后将回调返回给客户端,控制权则返回给服务,服务会重入并重新获取锁。这样就解决了死锁的问题。 第三种方案则是将回调操作设置为单向操作。此时,回调调用不会产生应答消息,服务操作一旦执行了回调操作,就会继续执行,回调对象不会争用与服务实例关联的锁,从而解决了死锁问题。

(4)       图例:

 

Wcf大数据量传输

1.       在绑定上指定消息大小的配额,能够增加对于较大消息的支持

2.       具体解决方式:

(1)       消息传输优化机制(MTOM

<wsHttpBinding>

         <binding name="wsHttpLargeMessage"maxReceivedMessageSize="5000000" messageEncoding="Mtom">

                   <readerQuotas maxArrayLength="5000000"/>

         </binding>

</wsHttpBinding>

(2)       MTOM处理传输整个消息仍然被加载到内存中,对于大量数据传输,数据流传递降低了内存的使用量。

 

Wcf实例模型

1.       通过ServiceBehaviorAttribute控制InstanceContextMod枚举的percall,persessionsingle,代码:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]

public class CounterServicePerCall:ICounterServicePerCall

2.       Percall服务

(1)       为每个调用创建新的服务对象

(2)       增加了整体的吞吐量

(3)       状态不会在多次调用中存在

(4)       内存开销较小

(5)       不会产生并发性问题

3.       Persession服务

(1)       asp.net中的session相比较,wcf中的persession是客户端发起的,而asp.net中的session是服务端初始化的。这样wcf中的session效率要高。

(2)       为每个客户端/代理创建新的服务对象(默认)

(3)       吞吐量较少,内存开销增大

(4)       状态由服务实例维护

(5)       引发多线程客户端的并发

(6)       仅当绑定支持会话时,才能够支持会话

(7)       在服务契约上需要设置能够提供会话功能, SessionMode 枚举(Allow(默认), NotAllowed, Required),代码:

[ServiceContract(SessionMode=SessionMode.Required)]

public interface ICounterServiceSession

{

     [OperationContract]

     int IncrementCounter();

}

(8)       SessionId信道的属性:

SessionServiceClient proxy=new SessionServiceClient ();

string s = proxy.InnerChannel.SessionId;

(9)       会话的生命周期默认是10分钟,如需要设置,代码如下:

<netTcpBinding>

    <binding name="netTcp" receiveTimeout="00:10:00" />

</netTcpBinding>

还可以通过操作显式地控制生命周期,设置OperationContractAttribute

IsInitiating(是否创建) IsTerminating(是否终止)属性,代码:

[ServiceContract(SessionMode = SessionMode.Required)]

public interface ISessionService

{

[OperationContract(IsInitiating = true, IsTerminating =false)]

void StartSession();

[OperationContract(IsInitiating = false, IsTerminating =false)]

void IncrementCounter();

[OperationContract(IsInitiating = false, IsTerminating =false)]

int GetCounter();

[OperationContract(IsInitiating = false, IsTerminating =false)]

string GetSessionId();

[OperationContract(IsInitiating = false, IsTerminating =true)]

void StopSession();

}

4.       单件模式single

(1)       为所有客户端的所有调用创建单一的服务对象

(2)       需要处理并发性问题。

(3)       通常要避免使用单件模型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值