[Chrome翻译]发现Cronet

我心飞翔 分类:javascript

原文地址:medium.com/@cchiappini…

原文作者:medium.com/@cchiappini

发布时间:2016年8月22日-5分钟阅读

Cronet是一个用于Android和iOS应用的网络库。Cronet是作为库打包的Chromium网络栈:这意味着Chrome浏览器每天都在使用这个栈。

采用Cronet可以通过降低延迟和增加吞吐量来提高应用的网络性能。

本文介绍了Cronet库及其使用方法。你可以在这里找到一个如何使用Cronet的例子。这个示例展示了如何使用Cronet加载一堆图片,存储在谷歌云上。

今天的网络

看起来每个人都在使用OkHttp的一些变体。你可以通过Android框架,直接使用OkHttp,或者Volley(配置为使用框架或OkHttp)。

框架版本的API,HttpUrlConnection,提供了一个在单线程上运行的同步API。

OkHttp提供了异步API、流和HTTP/2。

Volley提供了请求优先级、多并发网络请求和请求取消。Volley在解析过程中会在内存中保留响应,所以对于小的HTTP请求来说,它的处理能力更强。

而Cronet API则允许异步请求。

Chromium网络栈

Chromium网络协议栈提供了几个优势来改善页面加载时间。

每次主机建立连接时,都要进行各种活动,比如DNS解析和握手。Chromium协议栈使用Socket Late Binding机制来解决这个问题。

现代页面需要大量的资源,而资源优先级是浏览器的一个难题。Chromium协议栈使用了资源优先级,所有的请求都会以优先级标记发送给服务器,让服务器按照适当的优先级顺序进行响应。

Chromium还提供了一个磁盘缓存来缓存网络资源。

其他Cronet功能

在读写数据时,Cronet使用JAVA NIO ByteBuffers,为I/O功能提供了更好的性能。

作为Chromium网络栈,Cronet也允许设置请求的优先级。参见优先级部分的代码示例。

支持HTTP/2和QUIC

使用Cronet的优势之一是支持HTTP/2和QUIC。如果您熟悉这两个协议,可以随意跳过下面的章节,转到使用方法。

HTTP/2

HTTP/2通过进化标准,解决了目前HTTP的许多弊端。相对于其前身,HTTP/2。

  • 是二进制的,而不是文本的
  • 是完全多路复用的,而不是有序的和阻塞的:这允许使用一个连接做并行请求
  • 使用头压缩来减少开销
  • 允许服务器主动将响应 "推送 "到客户端缓存中。

QUIC

QUIC协议(Quick UDP Internet Connections)是谷歌在2012年宣布的,旨在用UDP代替TCP取代HTTP/2。

QUIC允许以更低的延迟创建连接,是一个没有线头阻塞的多路复用协议。这意味着它解决了数据包丢失的问题,只阻断单个数据流,而不是所有的数据流。

桌面和 Android Chrome 浏览器上的所有主要 Google 网站以及许多 Android 应用程序都使用了 QUIC。

性能测试报告显示,网页加载时间快了5%,网页搜索速度快了1秒,达到99%。YouTube是使用QUIC的地方之一,它报告说,通过减少30%的重音(视频暂停)数量,提高了体验质量。

使用情况

CronetEngine

第一步是实例化一个CronetEngine,你可以在ViewAdapter.java中找到。通常情况下,你只需要一个CronetEngine实例,所以在示例中,它是一个静态变量,由方法getCronetEngine(Context context)创建。

当创建CronetEngine时,通过CronetEngine.Builder,有各种配置选项。

  1. 控制缓存(选一个)
  • 通过使用100KB的内存缓存。
engineBuilder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_IN_MEMORY, 100 * 1024)
 

或者通过使用1MB的磁盘缓存。

engineBuilder.setStoragePath(storagePathString);
engineBuilder.enableHttpCache(CronetEngine.Builder.HttpCache.DISK,
 1024 * 1024);
 
  1. 使用以下方法启用HTTP2
 engineBuilder.enableHttp2(true)
 
  1. 使用以下方法启用QUIC
engineBuilder.enableQuic(true)
 
  1. 如果你知道服务器正在使用QUIC,你可以通过使用
engineBuilder.addQuicHint(...)
 

事实上,在收到第一个响应之前,Cronet并不知道服务器说的是QUIC,一开始也不会尝试使用它。使用addQuicHint(...)方法,就不需要发现服务器是否支持QUIC。此外,通过使用

cronetBuilder.setStoragePath(...)
cronetBuilder.enableHttpCache(CronetEngine.Builder.HTTP_CACHE_DISK_NO_HTTP, 1024 * 1024)
 

这些信息将在不同的会话中被持久化,并从第一次请求开始使用。使用磁盘缓存也会持久化服务器的加密信息,对于QUIC 0-rtt会话的建立,事实上0-rtt使用了之前协商好的会话中的QUIC服务器信息。

UrlRequest

在Android上,Cronet提供了自己的Java异步API。从ViewAdapter类中可以看到,首先你需要扩展UrlRequest.Callback来处理请求生命周期内的事件。

你有4个不同的回调方法,一旦请求完全和部分完成,就会被执行者调用。

onRedirectReceived(...)
onResponseStarted(...)
onReadCompleted(...)
onSucceeded(...)
 

一旦你实现了请求回调,你就可以通过使用UrlRequestBuilder进行请求,它将结合URL、回调、执行器和Cronet引擎。

// Create an executor to execute the request
Executor executor = Executors.newSingleThreadExecutor();
UrlRequest.Callback callback = new SimpleUrlRequestCallback(holder.imageViewCronet);
UrlRequest.Builder builder = new UrlRequest
.Builder(ImageRepository.getImage(position), callback, executor, cronetEngine);
// Start the request
builder.build().start();
 

优先级

一个请求可以有5种类型的优先级。

  • REQUEST_PRIORITY_IDLE.
  • REQUEST_PRIORITY_LOWEST(最低级)
  • REQUEST_PRIORITY_LOW(优先级低)
  • REQUEST_PRIORITY_MEDIUM(优先级)
  • REQUEST_PRIORITY_HIGHEST(最高优先级)

你可以通过使用builder的setPriority方法来设置Request的优先级。

builder.setPriority(UrlRequest.Builder.REQUEST_PRIORITY_HIGHEST);
 

HTTPURLConnection

如果你依赖于java.net.HttpURLConnection API,你可以通过使用Cronet实现。

HttpURLConnection connection = (HttpURLConnection)engine.openConnection(url);
URL.setURLStreamHandlerFactory(engine.createURLStreamHandlerFactory());
 

请注意,Cronet的HttpURLConnection实现在系统实现方面有一些限制。例如,它没有使用系统默认的HTTP缓存。考虑到要将async非阻塞API转换为同步阻塞API,Async API的性能可能比HttpURLConnection更强。

调试

您可以使用 NetLog 来获取更多有关 Cronet 如何处理网络请求的信息。
为了做到这一点,您需要通过调用 CronetEngine.startNetLogToFile 和 CronetEngine.stopNetLog 来检测代码以启动和停止 NetLog。请看一下示例中名为startNetLog()的方法,.NetLog()是一个很好的例子。

可以通过使用Chrome浏览器导航到chrome://net-internals#import 来读取日志文件。

这就是NetLog的样子。

image.png

请注意,开启NetLog跟踪会影响网络性能。

资料库

正如README文件上所描述的那样,今天获取最新版本的库是一个手动过程。
根据架构不同,库的大小在3-5MB之间。

结束语

Cronet是一个开源库,可以在Android和IOS上进行HTTP、HTTP/2和QUIC调用。今天就在你的应用上试试,以提高你的应用网络性能。

来源

www.chromium.org/developers/…

www.chromium.org/developers/…


通过www.DeepL.com/Translator(免费版)翻译

回复

我来回复
  • 暂无回复内容