提问人:Joffrey Ferreira 提问时间:6/26/2023 最后编辑:Joffrey Ferreira 更新时间:7/5/2023 访问量:270
将 Net Framework 4.7.1 升级到 Net 6 会降低 WCF 服务使用速度
Upgrade Net Framework 4.7.1 to Net 6 makes WCF service consumption slower
问:
我们正在将 .Net Framework 4.7.1 后端重写为 .Net 6,并且我们有了第一个版本。但是在本地执行性能测试时,我们观察到在相同的配置下,新后端的查询速度较慢。当使用WCF服务中的数据时,会发生这种情况:以前平均需要200毫秒,现在是650毫秒
我们在 web.config 中配置了连接的服务
<system.serviceModel>
<diagnostics performanceCounters="Off">
<messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true"/>
</diagnostics>
<bindings>
<basicHttpBinding>
<binding name="DocumentSecuredServiceBinding" bypassProxyOnLocal="false" receiveTimeout="00:10:00" sendTimeout="00:10:00" textEncoding="utf-8" messageEncoding="Mtom" maxReceivedMessageSize="209715200" maxBufferPoolSize="5242880" maxBufferSize="209715200">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint name="DocumentServiceImpl" address="https://service/DocumentSecuredService" binding="basicHttpBinding" bindingConfiguration="DocumentSecuredServiceBinding" behaviorConfiguration="CredentialIdentificationBehavior" contract="DocumentService.DocumentSecuredService"/>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="CredentialIdentificationBehavior">
<clientCredentials>
<clientCertificate findValue="CertName" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
现在,配置是从抽象工厂中的appsettings.json加载的,并实现:
public abstract class BaseSecuredServiceFactory
{
protected readonly X509Certificate2 _clientCertificate;
protected readonly Binding _binding;
protected readonly EndpointAddress _endpointAdress;
protected BaseSecuredServiceFactory(ILoggerFactory loggerFactory, EndpointOptions option)
{
_clientCertificate = LoadCertificate(option.CertificateSubjectName);
_binding = new BasicHttpBinding()
{
BypassProxyOnLocal = option.ByPassProxyOnLocal,
ReceiveTimeout = option.ReceiveTimeout,
SendTimeout = option.SendTimeout,
TextEncoding = Encoding.UTF8,
MessageEncoding = option.MessageEncoding,
MaxReceivedMessageSize = option.MaxReceivedMessageSize,
MaxBufferPoolSize = option.MaxBufferPoolSize,
MaxBufferSize = option.MaxBufferSize,
TransferMode = option.TransferMode,
Security = new BasicHttpSecurity()
{
Mode = option.SecurityMode,
Transport = new HttpTransportSecurity()
{
ClientCredentialType = HttpClientCredentialType.Certificate
}
}
};
_endpointAdress = new EndpointAddress(option.EndpointAdress);
}
protected static X509Certificate2 LoadCertificate(string subjectName)
{
// Load certificate from store My of LocalMachine
X509Store store = new(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = store.Certificates.Find(
X509FindType.FindBySubjectName,
subjectName,
false
);
if (certificates.Count == 0)
{
throw new InvalidOperationException(
$"The certificate with subject name '{subjectName}' could not be found."
);
}
return certificates[0];
}
}
public class DocumentSecuredServiceFactory
: BaseSecuredServiceFactory,
IDocumentSecuredServiceFactory
{
public DocumentSecuredServiceFactory(
ILoggerFactory loggerFactory,
IOptions<DocumentEndpointOptions> options
)
: base(loggerFactory, options.Value) { }
public DocumentSecuredServiceClient GetDocumentSecuredService()
{
DocumentSecuredServiceClient result = new(_binding, _endpointAdress);
result.Endpoint.EndpointBehaviors.Add(new InspectorBehavior(_loggerFactory));
result.ClientCredentials.ClientCertificate.Certificate = _clientCertificate;
return result;
}
}
appsettings.json中的配置部分
// Document Secured Service configuration
{
"ByPassProxyOnLocal": false,
"ReceiveTimeout": "00:10:00",
"SendTimeout": "00:10:00",
"MessageEncoding": "Mtom",
"MaxReceivedMessageSize": 209715200,
"MaxBufferPoolSize": 5242880,
"MaxBufferSize": 209715200,
"TransferMode": 0, // Buffered
"SecurityMode": 1,
"HttpClientCredentialType": 5,
"EndpointAdress": "https://service/DocumentSecuredService",
"CertificateSubjectName": "CertName"
}
以下是在 Net 6 中从本地 wsdl 文件生成的ConnectedService.json
{
"ExtendedData": {
"inputs": [
"../wsdl/DocumentSecuredServiceV002.wsdl"
],
"collectionTypes": [
"System.Array",
"System.Collections.Generic.Dictionary`2"
],
"namespaceMappings": [
"*, BslDocumentService"
],
"references": [
"AutoMapper, {AutoMapper, 12.0.0}",
"C:\\Source\\TIPI\\Tipi Backend\\Tipi.Backend.Web\\Tipi.Backend.Web.Services\\bin\\Debug\\net6.0\\Tipi.Backend.Web.Client.Models.dll",
"C:\\Source\\TIPI\\Tipi Backend\\Tipi.Backend.Web\\Tipi.Backend.Web.Services\\bin\\Debug\\net6.0\\Tipi.Backend.Web.Core.dll",
"C:\\Source\\TIPI\\Tipi Backend\\Tipi.Backend.Web\\Tipi.Backend.Web.Services\\bin\\Debug\\net6.0\\Tipi.Backend.Web.Data.dll",
"Microsoft.AspNetCore.Cryptography.Internal, {Microsoft.AspNetCore.Cryptography.Internal, 6.0.11}",
"Microsoft.AspNetCore.Cryptography.KeyDerivation, {Microsoft.AspNetCore.Cryptography.KeyDerivation, 6.0.11}",
"Microsoft.AspNetCore.Identity.EntityFrameworkCore, {Microsoft.AspNetCore.Identity.EntityFrameworkCore, 6.0.11}",
"Microsoft.Bcl.AsyncInterfaces, {Microsoft.Bcl.AsyncInterfaces, 5.0.0}",
"Microsoft.Data.Sqlite, {Microsoft.Data.Sqlite.Core, 6.0.11}",
"Microsoft.EntityFrameworkCore, {Microsoft.EntityFrameworkCore, 6.0.11}",
"Microsoft.EntityFrameworkCore.Abstractions, {Microsoft.EntityFrameworkCore.Abstractions, 6.0.11}",
"Microsoft.EntityFrameworkCore.Relational, {Microsoft.EntityFrameworkCore.Relational, 6.0.11}",
"Microsoft.EntityFrameworkCore.Sqlite, {Microsoft.EntityFrameworkCore.Sqlite.Core, 6.0.11}",
"Microsoft.Extensions.Caching.Abstractions, {Microsoft.Extensions.Caching.Abstractions, 6.0.0}",
"Microsoft.Extensions.Caching.Memory, {Microsoft.Extensions.Caching.Memory, 6.0.1}",
"Microsoft.Extensions.Configuration.Abstractions, {Microsoft.Extensions.Configuration.Abstractions, 6.0.0}",
"Microsoft.Extensions.DependencyInjection, {Microsoft.Extensions.DependencyInjection, 6.0.1}",
"Microsoft.Extensions.DependencyInjection.Abstractions, {Microsoft.Extensions.DependencyInjection.Abstractions, 6.0.0}",
"Microsoft.Extensions.DependencyModel, {Microsoft.Extensions.DependencyModel, 6.0.0}",
"Microsoft.Extensions.Identity.Core, {Microsoft.Extensions.Identity.Core, 6.0.11}",
"Microsoft.Extensions.Identity.Stores, {Microsoft.Extensions.Identity.Stores, 6.0.11}",
"Microsoft.Extensions.Localization.Abstractions, {Microsoft.Extensions.Localization.Abstractions, 7.0.0}",
"Microsoft.Extensions.Logging, {Microsoft.Extensions.Logging, 6.0.0}",
"Microsoft.Extensions.Logging.Abstractions, {Microsoft.Extensions.Logging.Abstractions, 6.0.0}",
"Microsoft.Extensions.ObjectPool, {Microsoft.Extensions.ObjectPool, 5.0.10}",
"Microsoft.Extensions.Options, {Microsoft.Extensions.Options, 6.0.0}",
"Microsoft.Extensions.Primitives, {Microsoft.Extensions.Primitives, 6.0.0}",
"Microsoft.IdentityModel.Logging, {Microsoft.IdentityModel.Logging, 6.8.0}",
"Microsoft.IdentityModel.Protocols.WsTrust, {Microsoft.IdentityModel.Protocols.WsTrust, 6.8.0}",
"Microsoft.IdentityModel.Tokens, {Microsoft.IdentityModel.Tokens, 6.8.0}",
"Microsoft.IdentityModel.Tokens.Saml, {Microsoft.IdentityModel.Tokens.Saml, 6.8.0}",
"Microsoft.IdentityModel.Xml, {Microsoft.IdentityModel.Xml, 6.8.0}",
"Microsoft.Win32.SystemEvents, {Microsoft.Win32.SystemEvents, 7.0.0}",
"Newtonsoft.Json, {Newtonsoft.Json, 13.0.1}",
"NLog, {NLog, 5.0.5}",
"NLog.Extensions.Logging, {NLog.Extensions.Logging, 5.1.0}",
"NLog.Web.AspNetCore, {NLog.Web.AspNetCore, 5.1.5}",
"Oracle.EntityFrameworkCore, {Oracle.EntityFrameworkCore, 6.21.90}",
"Oracle.ManagedDataAccess, {Oracle.ManagedDataAccess.Core, 3.21.90}",
"SQLitePCLRaw.batteries_v2, {SQLitePCLRaw.bundle_e_sqlite3, 2.0.6}",
"SQLitePCLRaw.core, {SQLitePCLRaw.core, 2.0.6}",
"SQLitePCLRaw.provider.e_sqlite3, {SQLitePCLRaw.provider.e_sqlite3, 2.0.6}",
"System.Collections.Immutable, {System.Collections.Immutable, 6.0.0}",
"System.Configuration.ConfigurationManager, {System.Configuration.ConfigurationManager, 6.0.0}",
"System.Diagnostics.DiagnosticSource, {System.Diagnostics.DiagnosticSource, 6.0.0}",
"System.Diagnostics.PerformanceCounter, {System.Diagnostics.PerformanceCounter, 6.0.0}",
"System.DirectoryServices, {System.DirectoryServices, 7.0.0}",
"System.DirectoryServices.Protocols, {System.DirectoryServices.Protocols, 5.0.1}",
"System.Drawing.Common, {System.Drawing.Common, 7.0.0}",
"System.Formats.Asn1, {System.Formats.Asn1, 6.0.0}",
"System.IO, {System.IO, 4.3.0}",
"System.Reflection.DispatchProxy, {System.Reflection.DispatchProxy, 4.7.1}",
"System.Runtime, {System.Runtime, 4.3.0}",
"System.Runtime.CompilerServices.Unsafe, {System.Runtime.CompilerServices.Unsafe, 6.0.0}",
"System.Security.AccessControl, {System.Security.AccessControl, 6.0.0}",
"System.Security.Cryptography.Cng, {System.Security.Cryptography.Cng, 4.5.0}",
"System.Security.Cryptography.Pkcs, {System.Security.Cryptography.Pkcs, 6.0.1}",
"System.Security.Cryptography.ProtectedData, {System.Security.Cryptography.ProtectedData, 6.0.0}",
"System.Security.Cryptography.Xml, {System.Security.Cryptography.Xml, 6.0.1}",
"System.Security.Permissions, {System.Security.Permissions, 7.0.0}",
"System.Security.Principal.Windows, {System.Security.Principal.Windows, 5.0.0}",
"System.ServiceModel, {System.ServiceModel.Primitives, 4.10.2}",
"System.ServiceModel.Duplex, {System.ServiceModel.Duplex, 4.10.2}",
"System.ServiceModel.Federation, {System.ServiceModel.Federation, 4.10.2}",
"System.ServiceModel.Http, {System.ServiceModel.Http, 4.10.2}",
"System.ServiceModel.NetTcp, {System.ServiceModel.NetTcp, 4.10.2}",
"System.ServiceModel.Primitives, {System.ServiceModel.Primitives, 4.10.2}",
"System.ServiceModel.Security, {System.ServiceModel.Security, 4.10.2}",
"System.Text.Encoding, {System.Text.Encoding, 4.3.0}",
"System.Text.Encodings.Web, {System.Text.Encodings.Web, 6.0.0}",
"System.Text.Json, {System.Text.Json, 6.0.0}",
"System.Threading.Tasks, {System.Threading.Tasks, 4.3.0}",
"System.Windows.Extensions, {System.Windows.Extensions, 7.0.0}",
"System.Xml.ReaderWriter, {System.Xml.ReaderWriter, 4.3.0}",
"System.Xml.XmlDocument, {System.Xml.XmlDocument, 4.3.0}"
],
"sync": true,
"targetFramework": "net6.0",
"typeReuseMode": "All"
}
}
我已更新到最新版本的System.ServiceModel软件包(6.0.0)。在以前的后端,它是 4.0.0 版本。我使用了 svcUtil 版本 2.1.0
我已经比较了两个服务对象实例化,我看不出任何可以解释性能缓慢的差异
我还尝试更改一些设置并使用其他绑定(NetTcpBinding 和 WSHttpBinding)但没有成功
我们只在 WCF 服务的客户端工作
提前感谢您的帮助
编辑由于此更改,我已将新时间提高到 500 毫秒 https://github.com/dotnet/wcf/issues/5002
答:
1赞
Joffrey Ferreira
7/5/2023
#1
在WCF团队github上创建问题后,提出了两种解决方案:
- 使用 HttpClientFactory,但它需要对我们的代码进行大量修改
- 在第一个客户端实例之前添加。我们这样做了,性能比我们当前的 API 更快
DocumentSecuredServiceV002Client.CacheSetting = CacheSetting.AlwaysOn;
评论
svcutil