DotNet关键知识点——WCF篇(五)

WCF调试和内部机制

1. 客户端跟踪

了解.NET的Tracing机制可以知道,它主要由Source-Switch,Filter-Listener架构组成。跟踪也可在文件app.config中配置。
以一个典型客户端的配置文件格式为例:

<configuration>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel" ... propagateActivity ="true/false">...</source>  if activity crosses boundary
      <source name="System.ServiceModel.MessageLogging"
          switchValue="Information">    source及其switch

        <listeners>                     为这个source添加listener
        
<add name="log" type="System.Diagnostics.XmlWriterTraceListener"
             initializeData="Traces.svclog" />

        </listeners>
      </source>
    </sources>
    <sharedListeners name="…">           也对为多个source配置共享的listener,使用只要add name引用即可
    </sharedListeners>

    <trace autoflush="true" />           每次打印直接输出(此处到文件)而不缓冲
  </system.diagnostics>
  <system.serviceModel>
      <diagnostics>
       
<messageLogging
             logEntireMessage="true"
             logMalformedMessages="false"
             logMessagesAtServiceLevel="true"        记录服务级的消息
             logMessagesAtTransportLevel="false"     记录传输级的消息 
             maxMessagesToLog="3000"
             maxSizeOfMessageToLog="2000"> 
         
<filters>                     filter和messageLogging采用WCF特有的设置
            <add
nodeQuota="10"  (可选,设置匹配过程中最大搜索节点数)
                 xmlns:soap="
http://www.w3.org/2003/05/soap-envelope"
                 xmlns:a="
http://www.w3.org/2005/08/addressing" >
              /soap:Envelope/soap:Header/a:Action[
              starts-with(text(),'
http://schemas.xmlsoap.org')]     设置XPath用于匹配
            </add>
          </filters> 
        </messageLogging>
      </diagnostics>
     … system.serviceModel内客户端的其他配置

2. 端到端跟踪

活动(Activities)是WCF端到端跟踪中基本信息单元。
活动不是对象,而是WCF进行处理活动的一些节点。活动一般可以解释为:当X正在发生时,跟踪就产生。
为了实现端到端跟踪,在client和service的source的propagateActivity属性均需设置为true,这样一个跟踪就可以产生一个转移跟踪(Trace Transfer)。
用Guid.NewGuid()创建一个Guid对象
Trace.CorrelationManager.ActivityId用来设置当前活动的GUID。
ts.TraceTransfer(int eventId, string message, Guid relatedActivityId)用来发生转移,relatedActivityId为转入时为新的GUID,转回时为原GUID。

3. WCF扩展和检视

3.1 参数检视

接口:

interface IParameterInspector {
    object BeforeCall(string operationName, object[] inputs);
    void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState);
}

客户端:
BeforeCall在参数序列化之前发生;AfterCall在消息返回参数反序列化之后发生。当参数不正确,需要阻止传递时,应抛出FaultException。
在proxy创建后,用proxy.Endpoint.Contract.Operations[0].Behaviors.Add(new XXXInspector())安装。

服务端:
BeforeCall在消息到达,参数反序列化后发生;AfterCall在处理完成消息返回,参数序列化之前发生。
安装通过实现一个实现IOperationBehavior的Attribute完成,其中接口要求实现以下方法:
void ApplyDispatcherBehavior(OperationDescription operationDescription, DispatchDescription dispatchDescription)
  (服务端设置)通常在其中安装检视器:dispatchOperation.ParameterInspectors.Add(new XXXInspector())
void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
  (客户端设置,在服务端不必实现)
void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
void Validate(OperationDescription operationDescription)

3.2 消息检视

客户端:
interface IClientMessageInspector {
    object BeforeSendRequest(ref Message request, IClientChannel channel);
       // 在请求消息送出前发生,返回correlationState,在AfterReceiveReply中出现
    void AfterReceiveReply(ref Message reply, object correlationState);
       // 在响应消息受到后发生
}

服务端:
interface IDispatchMessageInspector {
    object AfterReceiveRequest(ref Message request, IClientChannel channel,
                                                InstanceContext instanceContext);
      // 在请求消息受到发生,instanceContext包含service信息,返回correlationState,在BeforeSendReply中出现
    void BeforeSendReply(ref Message reply, object correlationState);
      // 在响应消息发出前发生
}

消息Message是流式对象,其状态MessageState包含Created, Written, Read, Copied, Closed,在Created状态下可以处理其消息体,只能处理一次,其后就进入Written, Read或Copied态。因此在上述消息检视中必须先复制再使用,以上述request为例:
MessageBuffer buffer = request.CreateBufferedCopy(Int32.MaxValue);
T body = request.CreateMessage().GetBody<T>();  // 获得消息体可供查阅
request = buffer.CreateMessage();  // 至此request又赋予一个初始态的Message对象

装载:

实现:
interface IEndpointBehavior {
    void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime);
    void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher); 
    void AddBindingParameters(ServiceEndpoint endpoint,
                                         BindingParameterCollection bindingParameters);
    void Validate(ServiceEndpoint endpoint);
}
设置:
创建继承于BehaviorExtensionElement。重载Type BehavioerType { get; }返回上述实现的Behavior的类型;重载object CreateBehavior(),返回一个新建的上述Behavior对象。
在配置文件中做如下设置(type中内容必须严格字符一致)
<system.ServiceModel> <behaviors>
<behavior name="Behavior的类名">
  <messageLogger />

</behaviors>
<extensions> <behaviorExtensions>
<add name="messageLogger "
  type="assembly.LoggingBehaviorExtensionElement, assembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>

 

posted @ 2010-01-29 23:00  quanben  阅读(228)  评论(0编辑  收藏  举报