将旧版 .NET 4.8 系统升级到 .NET 8 后,当系统使用
nettcp
绑定调用 WCF 服务时,我们发现托管在 Linux 上时对 WCF 服务的调用执行速度非常慢。
在 Windows 上运行的相同 .NET 8 代码可以在 20 毫秒内“ping”服务器,但在 Linux 中,无论是在金属上还是在容器中,都需要 150 毫秒才能“ping”(字面意思是只返回 true 的方法)。呼叫和安全执行否则有效。
我们使用自签名证书来托管 WCF 服务。这些都在
TrustedPeople
商店里。
证书通过 /root/.dotnet/corefx/cryptography/x509stores
安装到客户端容器中
.NET 4.8 中服务器是这样配置的
<behavior name="netTcpBindingBehavior">
<callbackDebug includeExceptionDetailInFaults="true" />
<clientCredentials>
<clientCertificate findValue="CN=local.oursystem.test" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectDistinguishedName" />
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
经过多次调试,发现使用
CertificateValidationMode=PeerTrust
在Linux下比Windows下运行速度非常慢。
实施自定义验证器加快了速度
/// <summary>
/// PeerTrust mode is slow in Linux, so implement our own validator
/// </summary>
private class WcfServerX509CertificateValidator : X509CertificateValidator
{
string _expectedThumbprint;
public WcfServerX509CertificateValidator(string expectedThumbprint)
{
Guard.NullOrEmpty(expectedThumbprint, "Certificate thumbprint required");
_expectedThumbprint = expectedThumbprint;
}
public override void Validate(X509Certificate2 certificate)
{
Guard.That(certificate.Thumbprint == _expectedThumbprint, () => $"Certificate was not issued by a trusted issuer. Received thumbprint={certificate.Thumbprint}, expected={_expectedThumbprint}");
}
}
ChannelFactory<T>
是用此片段配置的
var serviceCertificate = factory.Credentials.ServiceCertificate;
serviceCertificate.SslCertificateAuthentication = new X509ServiceCertificateAuthentication();
var sslCertificateAuthentication = serviceCertificate.SslCertificateAuthentication;
sslCertificateAuthentication.CertificateValidationMode = X509CertificateValidationMode.Custom; // PeerTrust is slow under Linux
sslCertificateAuthentication.CustomCertificateValidator = new WcfServerX509CertificateValidator(serverCertificate.Thumbprint);