写在前面
Microsoft.Extensions.ObjectPool 是 ASP.NET Core 基础结构的一部分,当对象的初始化成本较高,并且可能被频繁使用时,才适合采用对象池技术;被ObjectPool管理的对象不会进入垃圾回收,使用时通过由实例对象实现的Get()方法,从对象池中借出对象,用完之后调用Return(T obj)方法,将对象还回去。也可以在Return(T obj)方法中设置判断条件,仅允许特定的对象进入对象池。
通过NuGet 获取 Microsoft.Extensions.ObjectPool 类库
代码实现
using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.ObjectPool; using System.Security.Cryptography; using System.Text; var builder = WebApplication.CreateBuilder(args); // DefaultPooledObjectPolicy: 默认的策略,继承抽象类PooledObjectPolicy builder.Services.TryAddSingleton<ObjectPoolProvider, DefaultObjectPoolProvider>(); builder.Services.TryAddSingleton<ObjectPool<ReusableBuffer>>(serviceProvider => { var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>(); var policy = new DefaultPooledObjectPolicy<ReusableBuffer>(); return provider.Create(policy); }); builder.Services.TryAddSingleton<ObjectPool<Person>>(serviceProvider => { var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>(); var policy = new PersonPoolPolicy(); return provider.Create(policy); }); builder.Services.TryAddSingleton<ObjectPool<StringBuilder>>(serviceProvider => { var provider = serviceProvider.GetRequiredService<ObjectPoolProvider>(); var policy = new StringBuilderPooledObjectPolicy(); return provider.Create(policy); }); var app = builder.Build(); // config middleware app.UseMiddleware<BirthdayMiddleware>(); app.MapGet("/", () => "Hello rjcql!"); // return the SHA256 hash of a word http://localhost:5128/hash/xxxx app.MapGet("/hash/{word}", (string word, ObjectPool<ReusableBuffer> bufferPool) => { var buffer = bufferPool.Get(); try { // Set the buffer data to the ASCII values of a word for (var i = 0; i < word.Length; i++) { buffer.Data[i] = (byte)word[i]; } Span<byte> hash = stackalloc byte[32]; SHA256.HashData(buffer.Data.AsSpan(0, word.Length), hash); return "Hash: " + Convert.ToHexString(hash); } finally { // Data is automatically reset because this type implemented IResettable bufferPool.Return(buffer); } }); app.MapGet("/create/{name}", (string name, ObjectPool<Person> personPool) => { var person = personPool.Get(); try { person.Id = Guid.NewGuid().ToString("N"); var lastName = person.Name; // 这个是上一个对象的值 person.Name = name; return $"{person.Id}:{person.Name}, {lastName}"; } finally { // 根据条件回收 personPool.Return(person); } }); app.Run(); public class ReusableBuffer : IResettable { public byte[] Data { get; } = new byte[1024 * 1024]; // 1 MB public bool TryReset() { Array.Clear(Data); return true; } } public class Person { public string Id { get; set; } public string Name { get; set; } } public class PersonPoolPolicy : PooledObjectPolicy<Person> { public override Person Create() { return new Person { Id = "", Name = "rjcql" }; } public override bool Return(Person p) { if (p.Name != "rjcql") { // 不允许其他名称的对象放入对象池 return false; } return true; } } /// <summary> /// 创建中间件 /// </summary> public class BirthdayMiddleware { private readonly RequestDelegate _next; public BirthdayMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context, ObjectPool<StringBuilder> builderPool) { var stringBuilder = builderPool.Get(); try { stringBuilder.Append("Hi"); // 在中间干点啥别的 // await context.Response.WriteAsync(stringBuilder.ToString()); await _next.Invoke(context); } finally // 即使出错也要保证归还对象 { builderPool.Return(stringBuilder); } } }
调用示例
因为设置了回收条件,所以只有名字为rjcql的对象才会被回收,所以每次调用都先把rjcql对象取出。
到此这篇关于ASP.NET Core中的对象池化技术详解的文章就介绍到这了,更多相关.NET Core对象池内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » ASP.NET Core中的对象池化技术详解
发表评论 取消回复