
作为一家日活用户超过50万的中型电商平台的高级软件工程师,为旺季做准备始终是一项高风险的挑战。去年,在2023年黑色星期五期间,我们基于.NET 8的平台面临着重大的性能障碍。这些经验教训影响了我们今年的策略,目前我们正在测试.NET 9预览版的功能以优化我们的系统。以下是我们如何利用新技术以及过往经验来进行改进的情况。
我们所遇到的这些挑战凸显了对更好的可扩展性和效率的需求:
这些问题为需要优化的领域提供了关键的洞察依据。
缓存通过减少对数据库的依赖,在提升性能方面起着至关重要的作用。以下是我们在.NET 8中的当前实现:
public classProductCatalogService
{
privatereadonlyIMemoryCache _memoryCache;
privatereadonlyIDistributedCache _redisCache;
publicasyncTask<Product>GetProduct(string sku)
{
var cacheKey =$"product_{sku}";
var product =await _memoryCache.GetAsync<Product>(cacheKey);
if(product!=null)return product;
product =await _redisCache.GetAsync<Product>(cacheKey);
if(product!=null)
{
await _memoryCache.SetAsync(cacheKey, product, TimeSpan.FromMinutes());
return product;
}
product =await _dbContext.Products
.Include(p => p.Categories)
.Include(p => p.Inventory)
.FirstOrDefaultAsync(p => p.Sku == sku);
await _memoryCache.SetAsync(cacheKey, product, TimeSpan.FromMinutes());
await _redisCache.SetAsync(cacheKey, product, TimeSpan.FromHours());
return product;
}
}
负载测试结果(.NET 8):
.NET 9引入了一个混合缓存系统,它简化了缓存并提升了性能。以下是我们更新后的实现:
public classProductCatalogService
{
privatereadonlyIHybridCache _cache;
publicasyncTask<Product>GetProduct(string sku)
{
returnawait _cache.GetOrSetAsync(
$"product_{sku}",
async()=>await _dbContext.Products
.Include(p => p.Categories)
.Include(p => p.Inventory)
.FirstOrDefaultAsync(p => p.Sku == sku),
newHybridCacheOptions
{
MemoryExpirationTime = TimeSpan.FromMinutes(),
DistributedExpirationTime = TimeSpan.FromHours(),
SlidingExpiration =true
});
}
}
使用.NET 9混合缓存的早期结果

大型XML产品数据推送需要优化解析以处理大量更新。以下是我们目前在.NET 8中的实现:
public classProductFeedProcessor
{
publicasyncTaskProcessFeed(string xmlContent)
{
var products = xmlContent
.Split(new[]{"</product>"}, StringSplitOptions.RemoveEmptyEntries)
.Where(p => p.Contains("<product>"))
.Select(p =>ParseProduct(p));
foreach(var batch in products.Chunk())
{
await _dbContext.BulkInsertAsync(batch);
}
}
privateProductParseProduct(string xml)
{
var nameStart = xml.IndexOf("<name>")+;
var nameEnd = xml.IndexOf("</name>");
returnnewProduct{ Name = xml.Substring(nameStart, nameEnd - nameStart)};
}
}
负载下的内存概况:
.NET 9允许使用 Span 来更高效地处理内存和字符串。以下是更新后的实现:
public classProductFeedProcessor
{
publicasyncTaskProcessFeed(ReadOnlySpan<char> xmlContent)
{
var products =newList<Product>();
var reader =newSpanReader(xmlContent);
while(reader.TryReadTo("<product>",outvar productSpan))
{
if(reader.TryReadTo("</product>",outvar productContent))
{
products.Add(ParseProduct(productContent));
if(products.Count >=)
{
await _dbContext.BulkInsertAsync(products);
products.Clear();
}
}
}
}
privateProductParseProduct(ReadOnlySpan<char> productXml)
{
returnnewProduct
{
Name = productXml.SliceBetween("<name>","</name>").ToString(),
};
}
}
使用.NET 9的初步结果

我们分阶段的方法确保了平稳的迁移和优化过程:
对.NET 9的初步测试已经显示出很有前景的改进,包括: