我在运行连接到CRM的WCF服务时遇到问题:它经常产生CommunicationObjectAbortedExceptions,这让我想知道我是否做错了什么。许多人开始使用它们之后开始发生这些行为,在测试系统上它没有问题。
但是让我们从头开始:我编写了两个WCF服务,使用我自己的库连接到Microsoft CRM2013组织服务,以在CRM上执行查询。这些服务定期从CRM中调用,每天大约有100-200人使用。
这种方法基本上没问题,但我经常得到一些例外情况,如下所示(请参阅完整堆栈跟踪的帖子底部):
System.ServiceModel.CommunicationObjectAbortedException:对'
http://crm/MyOrganization/XRMServices/2011/Organization.svc
'的HTTP请求被流产了。这可能是由于当请求仍在进行时本地通道被关闭。如果不需要此行为,则更新代码,以便在请求操作仍在进行时不会关闭通道。
通常我的意思是每天大约100次,大多数情况下,每隔5-30分钟会抛出几个例外,分批的3-6个例外。我不知道为什么会这样。我在两个服务中使用我的库中的以下类初始化与CRM组织服务的连接:
public class CrmManager : IDisposable
{
private static CrmConnection s_connection;
public static CrmConnection Connection
{
get
{
if (s_connection == null)
{
s_connection = new CrmConnection("CrmTvTest");
}
return s_connection;
}
}
public static IOrganizationService ServiceProxy
{
get { return s_serviceProxy ?? (s_serviceProxy = new CachedOrganizationService(Connection)); }
}
可以看出,我每个WCF服务连接一次组织服务,使用CrmConnection
来处理连接细节,这些细节存储在一个静态变量中(充当单例,因为建立连接是昂贵,不应该经常做我的理解)。然后将其传递给CachedOrganizationService
,由于相同的原因,它是静态的。 WCF服务使用默认实例管理(PerSession
AFAIK),这意味着每个用户可能有1个连接和组织服务。
我的连接字符串看起来像这样(当然删除了任何合理的数据):
<connectionStrings>
<add name="CrmTvTest" connectionString="Url=http://crm/MyOrganization; Username=user; Password=pw;"/>
然后,我使用与CrmServiceContext
对象的连接,使用我的CrmManager类中的此方法执行查询。当然,这总是在using语句中调用:
using (CrmServiceContext context = new CrmServiceContext(CrmManager.ServiceProxy))
{
// do some stuff...
}
如何防止这些异常不断发生?我觉得这与CRM连接使用的安全令牌有关,但是当我使用CrmConnection
类时,这不应该是一个问题。它应该自动刷新它们。
任何建议都会非常受欢迎,因为我现在正在思考这个问题。
更新1
我切换到使用Developer Extensions并使用CrmConnector类,但没有用(我更新了上面的代码)。我还尝试将CrmConnection
类直接传递给CrmServiceContext:
using (CrmServiceContext context = new CrmServiceContext(CrmManager.Connection))
导致了与in this Stackoverflow Question相同的问题,没有使用负载均衡器(我们最初做过,但禁用负载平衡以消除导致问题的可能性。
完整Stacktrace:
---&GT; System.Net.WebException:请求已中止:请求已取消。 在System.Net.HttpWebRequest.GetResponse() at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) ---内部异常堆栈跟踪结束---
服务器堆栈跟踪: 在System.ServiceModel.Channels.HttpChannelUtilities.ProcessGetResponseWebException(WebException webException,HttpWebRequest request,HttpAbortReason abortReason) 在System.ServiceModel.Channels.HttpChannelFactory
1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout) at System.ServiceModel.Channels.SecurityChannelFactory
1.SecurityRequestChannel.Request(消息消息,TimeSpan超时) 在System.ServiceModel.Channels.ServiceChannel.Call(String action,Boolean oneway,ProxyOperationRuntime operation,Object [] ins,Object [] outs,TimeSpan timeout) 在System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall,ProxyOperationRuntime操作) 在System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)在[0]处重新抛出异常: 在System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg,IMessage retMsg) 在System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&amp; msgData,Int32 type) 在Microsoft.Xrm.Sdk.IOrganizationService.Execute(OrganizationRequest request) 在Microsoft.Xrm.Sdk.Client.OrganizationServiceProxy.ExecuteCore(OrganizationRequest请求) 在Microsoft.Xrm.Sdk.Client.OrganizationServiceContext.Execute(OrganizationRequest request) 在Microsoft.Xrm.Sdk.Linq.QueryProvider.RetrieveEntityCollection(OrganizationRequest请求,NavigationSource源) 在Microsoft.Xrm.Sdk.Linq.QueryProvider.Execute(QueryExpression qe,Boolean throwIfSequenceIsEmpty,Boolean throwIfSequenceNotSingle,Projection projection,NavigationSource source,List
1 linkLookups, String& pagingCookie, Boolean& moreRecords) at Microsoft.Xrm.Sdk.Linq.QueryProvider.Execute[TElement](QueryExpression qe, Boolean throwIfSequenceIsEmpty, Boolean throwIfSequenceNotSingle, Projection projection, NavigationSource source, List
1 linkLookups) 在Microsoft.Xrm.Sdk.Linq.QueryProvider.Execute [TElement](表达式表达式) 在Microsoft.Xrm.Sdk.Linq.QueryProvider.System.Linq.IQueryProvider.Execute [TResult](表达式表达式) 在System.Linq.Queryable.SingleOrDefault [TSource](IQueryable`1 source) 在CrmConnector.Entities.Contact.Get(Guid p_id,Boolean p_includeRelatedEntities)中的j:\ IntDev \ Libraries \ CrmConnector \ Entities \ Contact.cs:第63行 at CrmExtensionService.CrmExtension.GetPersonalizedEmailSignature(String p_contactId,String p_systemUserId)in j:\ IntDev \ Services \ CrmExtensionService \ CrmExtension.svc.cs:line 460
答案 0 :(得分:1)
我们遇到了同样的问题,负载均衡器是罪魁祸首。现在,我们通过在负载均衡器中进行少量配置来激活负载均衡器,从而解决了该错误。我们在负载均衡器上以最少的连接算法启用了粘性会话。因此,如果在负载平衡时未启用此功能,则即使同一会话失败,来自一台服务器的请求的经过身份验证的连接也会路由到其他服务器。一旦启用了粘性会话(会话持久性为客户端IP),请求就会发送到同一台服务器(在这种情况下,返回连接而不是新连接)。
答案 1 :(得分:0)
所以,在摆弄了大约两个月之后,我们发现了这个问题: CRM FrontEnd的负载平衡是罪魁祸首。我认为这也被禁用,禁用了我们的CRM服务的负载平衡,但它不是。我们的CRM服务定期与服务器1的组织服务建立连接,然后在运行中切换到服务器2并发生这些异常。
我们仍在尝试弄清楚如何在激活负载均衡的情况下使用它,但暂时我们将其禁用以防止这些错误弹出。
StackOverflow上有类似的案例:Sporadic exceptions calling a web service that is load balanced。我们目前正在使用webHttpBinding,并且很快就尝试切换到basicHttpBinding,但没有让它工作(但正如我所说,这只是一个快速的尝试)。