c# – IEndpointBehavior生命周期/日志服务调用
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了c# – IEndpointBehavior生命周期/日志服务调用,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3682字,纯文字阅读大概需要6分钟。
内容图文
![c# – IEndpointBehavior生命周期/日志服务调用](/upload/InfoBanner/zyjiaocheng/767/f4f020e94bfa467c89c9719c2a763c7b.jpg)
我正在尝试记录所有转发到服务引用的出站请求,包括完整的请求和响应正文.我以为我有一个使用behaviorExtensions的解决方案,但是在部署之后,很明显扩展是在多个请求之间共享的.
这是我目前的代码:
public class LoggingBehaviorExtender : BehaviorExtensionElement
{
public override Type BehaviorType => typeof(LoggingRequestExtender);
protected override object CreateBehavior() { return new LoggingRequestExtender(); }
}
public class LoggingRequestExtender : IClientMessageInspector, IEndpointBehavior
{
public string Request { get; private set; }
public string Response { get; private set; }
#region IClientMessageInspector
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
Request = request.ToString();
Response = null;
return null;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Response = reply.ToString();
}
#endregion
#region IEndpointBehavior
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { }
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(this);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { }
public void Validate(ServiceEndpoint endpoint) { }
#endregion
}
然后,当我到达记录点时,我提取行为……
var lre = client.Endpoint.Behaviors.OfType<LoggingRequestExtender>().FirstOrDefault();
var req = lre?.Request;
var resp = lre?.Response;
将调试日志记录添加到LoggingRequestExtender,我发现它只为多个请求实例化了一次.
有没有办法确保为每个线程实例化这个行为类?或者,在进行服务呼叫时,是否有更好的方法来获取完整的请求/响应主体?
编辑/部分答案:
自写这篇文章以来,我发现BeforeSendRequest返回的值作为correlationState传递给AfterReceiveReply,因此我可以使用guid连接请求和响应:
public virtual object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
var guid = Guid.NewGuid();
WebServiceLog.LogCallStart(guid, channel.RemoteAddress.ToString(), request.ToString());
return guid;
}
public virtual void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
Guid guid = (Guid)correlationState;
WebServiceLog.LogCallEnd(guid, reply.ToString());
}
我看到这种方法存在两个缺陷.一个是宜居的,这需要一个日志插入然后更新而不是单个插入.
第二个问题更多:在异常(例如超时)的情况下,我们从未点击AfterRecieveSupply,因此日志不知道发生了什么.我可以单独记录异常……
try
{
response = client.SomeFunction(request);
}
catch (Exception ex)
{
AppLog.Error("Some function failed", ex);
}
…但我看不到在BeforeSendRequest / AfterReceiveReply之外访问guid的方法,所以我没有任何东西可以将异常日志绑定到服务请求日志.
解决方法:
有几种方法可以解决这个问题.
1,您所描述的必须单独记录呼叫的情况不一定是这样的.如果您的WCF服务位于非负载平衡服务器中,则只需使用Guid作为密钥将请求添加到MemoryCache.当请求进入时,请拉出请求并一次登录.要捕获超时调用,您可以在一个线程上运行一个进程,该线程将每隔x分钟检查一次MemoryCache以进行拉出和记录(使用足够的锁来确保线程安全).
如果WCF服务处于负载平衡环境中,那么您所做的只是与上面相同,但存储到无sql类型的数据存储.
2,是否在您的范围内进行出站呼叫的代码进行了更改?如果是这样,您可以放弃创建行为扩展并创建一个定制的消息记录器.使用实现IDisposable的类,你可以编写像这样的好代码.
RequestMessage request = new RequestMessage();
ResponseMessage response = null;
using (_messageLogger.LogMessage(request, () => response, CallContextHelper.GetContextId(), enabled))
{
response = _outboundService.DoSomething(request);
}
这将不需要另一个进程来捕获将在dispose方法中处理的任何超时线程.
如果您需要更清晰,请告诉我,希望这有助于您……
内容总结
以上是互联网集市为您收集整理的c# – IEndpointBehavior生命周期/日志服务调用全部内容,希望文章能够帮你解决c# – IEndpointBehavior生命周期/日志服务调用所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。