Skip to content

Commit

Permalink
perf: Removed distributed cache and switched to using a dictionary fo…
Browse files Browse the repository at this point in the history
…r storing certificates.
  • Loading branch information
real-zony committed Jan 10, 2024
1 parent cf4d59a commit a9e2958
Show file tree
Hide file tree
Showing 5 changed files with 10 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
<PackageReference Include="Volo.Abp.BlobStoring" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.BackgroundWorkers" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.DistributedLocking.Abstractions" Version="$(AbpVersion)" />
<PackageReference Include="Volo.Abp.Json.Newtonsoft" Version="8.0.1" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,6 @@

namespace EasyAbp.Abp.WeChat.Pay.Security.PlatformCertificate;

// TODO: There might be performance issues here because serialization and deserialization operations are involved every time the cache is accessed. The best practice would be to cache the certificates directly in memory.
public class X509Certificate2JsonConverter : JsonConverter<X509Certificate2>
{
public override void WriteJson(JsonWriter writer, X509Certificate2 value, JsonSerializer serializer)
{
serializer.Serialize(writer, value.Export(X509ContentType.Pfx));
}

public override X509Certificate2 ReadJson(JsonReader reader, Type objectType, X509Certificate2 existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var bytes = serializer.Deserialize<byte[]>(reader);
return new X509Certificate2(bytes);
}
}

[Serializable]
public class PlatformCertificateEntity
{
Expand All @@ -32,7 +17,6 @@ public class PlatformCertificateEntity

public DateTime ExpireTime { get; set; }

[JsonConverter(typeof(X509Certificate2JsonConverter))]
public X509Certificate2 Certificate { get; set; }

public PlatformCertificateEntity()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using EasyAbp.Abp.WeChat.Pay.Options;
using EasyAbp.Abp.WeChat.Pay.Security.Extensions;
using EasyAbp.Abp.WeChat.Pay.Services;
using EasyAbp.Abp.WeChat.Pay.Services.OtherServices;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Logging;
using Volo.Abp;
using Volo.Abp.Caching;
using Volo.Abp.DependencyInjection;

namespace EasyAbp.Abp.WeChat.Pay.Security.PlatformCertificate;
Expand All @@ -19,38 +18,31 @@ public class PlatformCertificateManager : IPlatformCertificateManager, ISingleto
private readonly ILogger<PlatformCertificateManager> _logger;
private readonly IAbpWeChatPayServiceFactory _abpWeChatPayServiceFactory;
private readonly IAbpWeChatPayOptionsProvider _abpWeChatPayOptionsProvider;
private readonly IDistributedCache<PlatformCertificatesCacheItem> _distributedCache;
private readonly ConcurrentDictionary<string, Lazy<PlatformCertificateEntity>> _certificatesCache = new();

public PlatformCertificateManager(
ILogger<PlatformCertificateManager> logger,
IAbpWeChatPayServiceFactory abpWeChatPayServiceFactory,
IAbpWeChatPayOptionsProvider abpWeChatPayOptionsProvider,
IDistributedCache<PlatformCertificatesCacheItem> distributedCache)
IAbpWeChatPayOptionsProvider abpWeChatPayOptionsProvider)
{
_logger = logger;
_abpWeChatPayServiceFactory = abpWeChatPayServiceFactory;
_abpWeChatPayOptionsProvider = abpWeChatPayOptionsProvider;
_distributedCache = distributedCache;
}

public virtual async Task<PlatformCertificateEntity> GetPlatformCertificateAsync(string mchId, string serialNo)
{
Check.NotNullOrWhiteSpace(mchId, nameof(mchId));
Check.NotNullOrWhiteSpace(serialNo, nameof(serialNo));

var cacheItem = await _distributedCache.GetAsync(PlatformCertificatesCacheItemKey);
if (cacheItem != null)
{
return GetSpecifiedCachedCertificate(cacheItem, serialNo);
}
var cacheItem = _certificatesCache.TryGetValue(serialNo, out var lazyCertificate)
? lazyCertificate.Value
: null;
if (cacheItem != null) return cacheItem;

var options = await _abpWeChatPayOptionsProvider.GetAsync(mchId);

var certificateService = await _abpWeChatPayServiceFactory.CreateAsync<WeChatPayCertificatesWeService>(mchId);

cacheItem = new PlatformCertificatesCacheItem();
var cacheExpiration = TimeSpan.FromDays(31);

try
{
var certificates = await certificateService.GetPlatformCertificatesAsync();
Expand All @@ -62,35 +54,17 @@ public virtual async Task<PlatformCertificateEntity> GetPlatformCertificateAsync
certificate.EncryptCertificateData.Nonce,
certificate.EncryptCertificateData.Ciphertext);

cacheItem.Certificates.Add(certificate.SerialNo,
_certificatesCache.TryAdd(certificate.SerialNo,new Lazy<PlatformCertificateEntity>(() =>
new PlatformCertificateEntity(certificate.SerialNo, certificateString,
certificate.EffectiveTime, certificate.ExpireTime));
certificate.EffectiveTime, certificate.ExpireTime)));
}
}
catch (Exception e)
{
_logger.LogWarning("Fail to get and cache the platform certificates");
_logger.LogException(e);
cacheExpiration = TimeSpan.FromSeconds(10); // lock for 10s on failure.
}

await _distributedCache.SetAsync(PlatformCertificatesCacheItemKey, cacheItem,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = cacheExpiration
});

return GetSpecifiedCachedCertificate(cacheItem, serialNo);
}

protected virtual PlatformCertificateEntity GetSpecifiedCachedCertificate(
PlatformCertificatesCacheItem cacheItem, string serialNo)
{
if (!cacheItem.Certificates.TryGetValue(serialNo, out var secretModel))
{
throw new InvalidOperationException("Platform certificate not found.");
}

return secretModel;
return _certificatesCache[serialNo].Value;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
using System;
using System.IO;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using EasyAbp.Abp.WeChat.Pay.Security.PlatformCertificate;
Expand Down

0 comments on commit a9e2958

Please sign in to comment.