经过一段时间的工作后,IIS/ASP.Net 无法从 WCF Web 服务的 web.config 文件中读取设置
我们有一个运行在 IIS7 上的 ASP.Net Web 应用程序,与 WCF Web 服务进行通信,该服务处理从此 Web 应用程序到达的请求。
经过一段时间(可能是一周或几天)后,WCF Web 服务开始无法读取其 web.config 文件中的设置,并记录了以下异常:
System.NullReferenceException< /strong>
ABC.Communication.DataContract.RefreshRequest System.NullReferenceException: Object reference not set to an instance of an object.
at System.Xml.XmlNode.RemoveChild(XmlNode oldChild)
at System.Xml.XmlNode.RemoveAll()
at System.Xml.XmlElement.set_InnerXml(String value)
at System.Configuration.LocalFileSettingsProvider.XmlEscaper.Unescape(String escapedString)
at System.Configuration.LocalFileSettingsProvider.GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties)
at System.Configuration.SettingsBase.GetPropertiesFromProvider(SettingsProvider provider)
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at ABC.Communication.DataContract.Request.ValidateIpAddress() in C:\Project\ABC.Server\ABC.Communication\DataContract\Request.Validation.cs:line 955
at ABC.Communication.DataContract.RefreshRequestBase.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequestBase.cs:line 46
at ABC.Communication.DataContract.RefreshRequest.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequest.cs:line 30
at ABC.Communication.ClientCommunicationService.HandleRequest(Request request) in C:\Project\ABC.Server\ABC.Communication\ClientCommunicationService.cs:line 116
或 System.ArgumentException
ABC.Communication.DataContract.RefreshRequest System.ArgumentException: The node to be removed is not a child of this node.
at System.Xml.XmlNode.RemoveChild(XmlNode oldChild)
at System.Xml.XmlNode.RemoveAll()
at System.Xml.XmlElement.set_InnerXml(String value)
at System.Configuration.LocalFileSettingsProvider.XmlEscaper.Unescape(String escapedString)
at System.Configuration.LocalFileSettingsProvider.GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties)
at System.Configuration.SettingsBase.GetPropertiesFromProvider(SettingsProvider provider)
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at ABC.Communication.DataContract.Request.ValidateIpAddress() in C:\Project\ABC.Server\ABC.Communication\DataContract\Request.Validation.cs:line 955
at ABC.Communication.DataContract.RefreshRequestBase.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequestBase.cs:line 46
at ABC.Communication.DataContract.DataContracts.RefreshRequest.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequest.cs:line 30
at ABC.Communication.ClientCommunicationService.HandleRequest(Request request) in C:\Project\ABC.Server\ABC.Communication\ClientCommunicationService.cs:line 116
或 System.Configuration.SettingsPropertyNotFoundException:
ABC.Communication.DataContract.RefreshRequest System.Configuration.SettingsPropertyNotFoundException: The settings property 'ValidateIpConnections' was not found.
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at ABC.Communication.DataContract.Request.ValidateIpAddress() in C:\Project\ABC.Server\ABC.Communication\DataContract\Request.Validation.cs:line 955
at ABC.Communication.DataContract.RefreshRequestBase.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequestBase.cs:line 46
at ABC.Communication.DataContract.RefreshRequest.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequest.cs:line 30
at ABC.Communication.ClientCommunicationService.HandleRequest(Request request) in C:\Project\ABC.Server\ABC.Communication\ClientCommunicationService.cs:line 116
抛出此异常的代码非常简单:
private void ValidateIpAddress() {
// Load custom settings
CustomSettings settings = GetCustomSettings();
if (!settings.ValidateIpConnections) // here the exception is thrown!
return;
// the rest of code never reached...
}
现在可以在顶级父类 Request 如下所示:
public abstract partial class Request
{
/// <summary>
/// Custom settings.
/// </summary>
private static readonly CustomSettings customSettings;
/// <summary>
/// .cctor().
/// </summary>
static Request()
{
customSettings = new CustomSettings();
}
/// <summary>
/// Get custom settings.
/// </summary>
/// <returns>Custom settings.</returns>
internal static CustomSettings GetCustomSettings()
{
return customSettings;
}
// ....
}
不仅此特定设置 ValidateIpConnections 会出现此问题,WCF 服务的 web.config 文件中的其他设置也会出现此问题。
目前还不清楚这个问题的原因是什么,它不能持续稳定地重现。它似乎并不直接取决于负载/用户数量/打开的会话。有时,该网站可以顺利运行数周,然后该问题每周出现一次,然后连续出现几天。可能与应用程序池中某些工作进程的回收有关。
我们以前在 Windows Server 2003 (IIS 6.0) 上遇到它,现在在带有 IIS 7.0 的 Windows Server 2008 上遇到它,因此它似乎与 IIS 的版本没有直接关系。
我怀疑通过 Request 的只读静态成员为所有仅初始化一次的子类共享对 CustomSettings 类实例的访问可能存在问题。
任何帮助/建议将不胜感激。
We have an ASP.Net web application running on IIS7 communicating with WCF web service which handles the requests arriving from this web application.
After some time of work (it may be a week or just several days), the WCF web service starts to fail reading the settings in its web.config file, having logged the following exception(s):
System.NullReferenceException
ABC.Communication.DataContract.RefreshRequest System.NullReferenceException: Object reference not set to an instance of an object.
at System.Xml.XmlNode.RemoveChild(XmlNode oldChild)
at System.Xml.XmlNode.RemoveAll()
at System.Xml.XmlElement.set_InnerXml(String value)
at System.Configuration.LocalFileSettingsProvider.XmlEscaper.Unescape(String escapedString)
at System.Configuration.LocalFileSettingsProvider.GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties)
at System.Configuration.SettingsBase.GetPropertiesFromProvider(SettingsProvider provider)
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at ABC.Communication.DataContract.Request.ValidateIpAddress() in C:\Project\ABC.Server\ABC.Communication\DataContract\Request.Validation.cs:line 955
at ABC.Communication.DataContract.RefreshRequestBase.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequestBase.cs:line 46
at ABC.Communication.DataContract.RefreshRequest.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequest.cs:line 30
at ABC.Communication.ClientCommunicationService.HandleRequest(Request request) in C:\Project\ABC.Server\ABC.Communication\ClientCommunicationService.cs:line 116
or System.ArgumentException
ABC.Communication.DataContract.RefreshRequest System.ArgumentException: The node to be removed is not a child of this node.
at System.Xml.XmlNode.RemoveChild(XmlNode oldChild)
at System.Xml.XmlNode.RemoveAll()
at System.Xml.XmlElement.set_InnerXml(String value)
at System.Configuration.LocalFileSettingsProvider.XmlEscaper.Unescape(String escapedString)
at System.Configuration.LocalFileSettingsProvider.GetPropertyValues(SettingsContext context, SettingsPropertyCollection properties)
at System.Configuration.SettingsBase.GetPropertiesFromProvider(SettingsProvider provider)
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at ABC.Communication.DataContract.Request.ValidateIpAddress() in C:\Project\ABC.Server\ABC.Communication\DataContract\Request.Validation.cs:line 955
at ABC.Communication.DataContract.RefreshRequestBase.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequestBase.cs:line 46
at ABC.Communication.DataContract.DataContracts.RefreshRequest.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequest.cs:line 30
at ABC.Communication.ClientCommunicationService.HandleRequest(Request request) in C:\Project\ABC.Server\ABC.Communication\ClientCommunicationService.cs:line 116
or System.Configuration.SettingsPropertyNotFoundException:
ABC.Communication.DataContract.RefreshRequest System.Configuration.SettingsPropertyNotFoundException: The settings property 'ValidateIpConnections' was not found.
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at ABC.Communication.DataContract.Request.ValidateIpAddress() in C:\Project\ABC.Server\ABC.Communication\DataContract\Request.Validation.cs:line 955
at ABC.Communication.DataContract.RefreshRequestBase.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequestBase.cs:line 46
at ABC.Communication.DataContract.RefreshRequest.Validate() in C:\Project\ABC.Server\ABC.Communication\DataContract\RefreshRequest.cs:line 30
at ABC.Communication.ClientCommunicationService.HandleRequest(Request request) in C:\Project\ABC.Server\ABC.Communication\ClientCommunicationService.cs:line 116
The code which throws this exception is quite trivial:
private void ValidateIpAddress() {
// Load custom settings
CustomSettings settings = GetCustomSettings();
if (!settings.ValidateIpConnections) // here the exception is thrown!
return;
// the rest of code never reached...
}
Access to the instance of custom settings is implemented now in the top parent class Request as shown below:
public abstract partial class Request
{
/// <summary>
/// Custom settings.
/// </summary>
private static readonly CustomSettings customSettings;
/// <summary>
/// .cctor().
/// </summary>
static Request()
{
customSettings = new CustomSettings();
}
/// <summary>
/// Get custom settings.
/// </summary>
/// <returns>Custom settings.</returns>
internal static CustomSettings GetCustomSettings()
{
return customSettings;
}
// ....
}
The issue occurs not only for this specific setting ValidateIpConnections but also for other settings in the web.config file of the WCF service.
It is not clear at all what could be the reason of such issue, it is not reproducible constantly and stably. It does not seem to depend directly on the load/the number of users/open sessions. Sometimes the site is working smoothly for several weeks, then the issue occurs one time a week and then it occurs several days in a row. Possibly, it is related to recycling of some worker process in the application pool.
We used to encounter it on Windows Server 2003 (IIS 6.0) and now get it on Windows Server 2008 with IIS 7.0 so it does not seem to be directly related to the version of IIS.
I suspect there could be an issue with sharing access to the instance of CustomSettings class via readonly static member of Request for all the child classes which is initialized only once.
Any help/suggestion would be greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您可以避免使用自定义设置类,因为 web.config 在第一次访问时会被缓存。请参阅
ASP.NET:web.config 缓存在哪里/如何缓存?
所以不需要自己进行缓存,然后就可以排除这种情况。
我们的一台生产服务器上也遇到了类似的问题,结果发现病毒扫描程序正在扫描 web.config 文件,从而导致应用程序池回收。
我建议
I think you can avoid using the custom settings class because the web.config is cached the first time it is accessed. See
ASP.NET: Where/how is web.config cached?
So there's no need to do your own caching and then you can rule that one out.
We had a similar issue on one of our production servers and it turned out that the virus scanner was scanning the web.config file, which led to an application pool recycle.
I would recommend