ASP.NET Core中的响应压缩
2021-01-15 07:13
标签:intern 优先 ash img types test clu led pipe ????响应压缩技术是目前Web开发领域中比较常用的技术,在带宽资源受限的情况下,使用压缩技术是提升带宽负载的首选方案。我们熟悉的Web服务器,比如IIS、Tomcat、Nginx、Apache等都可以使用压缩技术,常用的压缩类型包括Brotli、Gzip、Deflate,它们对CSS、JavaScript、HTML、XML 和 JSON等类型的效果还是比较明显的,但是也存在一定的限制对于图片效果可能没那么好,因为图片本身就是压缩格式。其次,对于小于大约150-1000 字节的文件(具体取决于文件的内容和压缩的效率,压缩小文件的开销可能会产生比未压缩文件更大的压缩文件。在ASP.NET Core中我们可以使用非常简单的方式来使用响应压缩。 ????在ASP.NET Core中使用响应压缩的方式比较简单。首先,在ConfigureServices中添加services.AddResponseCompression注入响应压缩相关的设置,比如使用的压缩类型、压缩级别、压缩目标类型等。其次,在Configure添加app.UseResponseCompression拦截请求判断是否需要压缩,大致使用方式如下 如果需要自定义一些配置的话还可以手动设置压缩相关 ????关于响应压缩大致的工作方式就是,当发起Http请求的时候在Request Header中添加Accept-Encoding:gzip或者其他你想要的压缩类型,可以传递多个类型。服务端接收到请求获取Accept-Encoding判断是否支持该种类型的压缩方式,如果支持则压缩输出内容相关并且设置Content-Encoding为当前使用的压缩方式一起返回。客户端得到响应之后获取Content-Encoding判断服务端是否采用了压缩技术,并根据对应的值判断使用了哪种压缩类型,然后使用对应的解压算法得到原始数据。 通过上面的介绍,相信大家对ResponseCompression有了一定的了解,接下来我们通过查看源码的方式了解一下它大致的工作原理。 首先我们来查看注入相关的代码,具体代码承载在ResponseCompressionServicesExtensions扩展类中[点击查看源码??] 主要就是注入ResponseCompressionProvider和ResponseCompressionOptions,首先我们来看关于ResponseCompressionOptions[点击查看源码??] 关于这个类就不做过多介绍了,比较简单。ResponseCompressionProvider是我们提供响应压缩算法的核心类,具体如何自动选用压缩算法都是由它提供的。这个类中的代码比较多,我们就不逐个方法讲解了,具体源码可自行查阅[点击查看源码??],首先我们先看ResponseCompressionProvider的构造函数 其中BrotliCompressionProvider、GzipCompressionProvider是具体提供压缩方法的地方,咱们就看比较常用的Gzip的Provider的大致实现[点击查看源码??] 关于ResponseCompressionProvider其他相关的方法咱们在讲解UseResponseCompression中间件的时候在具体看用到的方法,因为这个类是响应压缩的核心类,现在提前说了,到中间件使用的地方可能会忘记了。接下来我们就看UseResponseCompression的大致实现。 UseResponseCompression具体也就一个无参的扩展方法,也比较简单,因为配置和工作都由注入的地方完成了,所以我们直接查看中间件里的实现,找到中间件位置ResponseCompressionMiddleware[点击查看源码??] 这个中间件非常的简单,就是初始化了ResponseCompressionBody。看到这里你也许会好奇,并没有触发调用压缩相关的任何代码,ResponseCompressionBody也只是调用了FinishCompressionAsync都是和释放相关的,不要着急我们来看ResponseCompressionBody类的结构 ????这个类实现了IHttpResponseBodyFeature,我们使用的Response.Body其实就是获取的HttpResponseBodyFeature.Stream属性。我们使用的Response.WriteAsync相关的方法,其实内部都是在调用PipeWriter进行写操作,而PipeWriter就是来自HttpResponseBodyFeature.Writer属性。可以大致概括为,输出相关的操作其核心都是在操作IHttpResponseBodyFeature。有兴趣的可以自行查阅HttpResponse相关的源码可以了解相关信息。所以我们的ResponseCompressionBody其实是重写了输出操作相关方法。也就是说,只要你调用了Response相关的Write或Body相关的,其实本质都是在操作IHttpResponseBodyFeature,由于我们开启了响应输出相关的中间件,所以会调用IHttpResponseBodyFeature的实现类ResponseCompressionBody相关的方法完成输出。和我们常规理解的还是有偏差的,一般情况下我们认为,其实只要针对输出的Stream做操作就可以了,但是响应压缩中间件竟然重写了输出相关的操作。
????了解到这个之后,相信大家就没有太多疑问了。由于ResponseCompressionBody重写了输出相关的操作,代码相对也比较多,就不逐一粘贴出来了,我们只查看设计到响应压缩核心相关的代码,关于ResponseCompressionBody源码相关的细节有兴趣的可以自行查阅[点击查看源码??],输出的本质其实都是在调用Write方法,我们就来查看一下Write方法相关的实现 通过上面的代码我们看到OnWrite方法是核心操作,我们直接查看OnWrite方法实现 从上面的逻辑我们可以看到,在执行压缩相关逻辑之前需要判断是否满足执行压缩相关的方法ShouldCompressResponse,这个方法是ResponseCompressionProvider里的方法,这里就不再粘贴代码了,本来就是判断逻辑我直接整理出来大致就是一下几种情况 通过以上的介绍我们可以大致了解到响应压缩的大致工作方式,简单总结一下 ????在查看相关代码之前,本来以为关于响应压缩相关的逻辑会非常的简单,看过了源码才知道是自己想的太简单了。其中和自己想法出入最大的莫过于在ResponseCompressionMiddleware中间件里,本以为是通过统一拦截输出流来进行压缩操作,没想到是对整体输出操作进行重写。因为在之前我们使用Asp.Net相关框架的时候是统一写Filter或者HttpModule进行处理的,所以存在思维定式。可能是Asp.Net Core设计者有更深层次的理解,可能是我理解的还不够彻底,不能够体会这样做的好处究竟是什么,如果你有更好的理解或则答案欢迎在评论区里留言解惑。
ASP.NET Core中的响应压缩 标签:intern 优先 ash img types test clu led pipe 原文地址:https://www.cnblogs.com/wucy/p/13395674.html介绍
使用方式
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseResponseCompression();
}
}
public void ConfigureServices(IServiceCollection services)
{
services.AddResponseCompression(options =>
{
//可以添加多种压缩类型,程序会根据级别自动获取最优方式
options.Providers.Add
源码探究
AddResponseCompression
public static class ResponseCompressionServicesExtensions
{
public static IServiceCollection AddResponseCompression(this IServiceCollection services)
{
services.TryAddSingleton
public class ResponseCompressionOptions
{
// 设置需要压缩的类型
public IEnumerable
public ResponseCompressionProvider(IServiceProvider services, IOptions
public class GzipCompressionProvider : ICompressionProvider
{
public GzipCompressionProvider(IOptions
UseResponseCompression
public class ResponseCompressionMiddleware
{
private readonly RequestDelegate _next;
private readonly IResponseCompressionProvider _provider;
public ResponseCompressionMiddleware(RequestDelegate next, IResponseCompressionProvider provider)
{
_next = next;
_provider = provider;
}
public async Task Invoke(HttpContext context)
{
//判断是否包含Accept-Encoding头信息,不包含直接大喊一声"抬走下一个"
if (!_provider.CheckRequestAcceptsCompression(context))
{
await _next(context);
return;
}
//获取原始输出Body
var originalBodyFeature = context.Features.Get
internal class ResponseCompressionBody : Stream, IHttpResponseBodyFeature, IHttpsCompressionFeature
{
}
public override void Write(byte[] buffer, int offset, int count)
{
//这是核心方法有关于压缩相关的输出都在这
OnWrite();
//_compressionStream初始化在OnWrite方法里
if (_compressionStream != null)
{
_compressionStream.Write(buffer, offset, count);
if (_autoFlush)
{
_compressionStream.Flush();
}
}
else
{
_innerStream.Write(buffer, offset, count);
}
}
private void OnWrite()
{
if (!_compressionChecked)
{
_compressionChecked = true;
//判断是否满足执行压缩相关的逻辑
if (_provider.ShouldCompressResponse(_context))
{
//匹配Vary头信息对应的值
var varyValues = _context.Response.Headers.GetCommaSeparatedValues(HeaderNames.Vary);
var varyByAcceptEncoding = false;
//判断Vary的值是否为Accept-Encoding
for (var i = 0; i
public virtual ICompressionProvider GetCompressionProvider(HttpContext context)
{
var accept = context.Request.Headers[HeaderNames.AcceptEncoding];
//判断请求头是否包含Accept-Encoding信心
if (StringValues.IsNullOrEmpty(accept))
{
Debug.Assert(false, "Duplicate check failed.");
return null;
}
//获取Accept-Encoding里的值,判断是否包含gzip、br、identity等,并返回匹配信息
if (!StringWithQualityHeaderValue.TryParseList(accept, out var encodings) || !encodings.Any())
{
return null;
}
//根据请求信息和设置信息计算匹配优先级
var candidates = new HashSet
总结
上一篇:phpexcel图片获取
下一篇:css文本样式
文章标题:ASP.NET Core中的响应压缩
文章链接:http://soscw.com/index.php/essay/42150.html