OkHttp3源码详解(四)缓存策略

  • 时间:
  • 浏览:2
  • 来源:uu快3游戏_uu快3计划_苹果版

ETag: "5694c7ef-24dc"

客户端再次请求时,可在头部加进如下域:

其主要逻辑要是将对应请求的meta数据写入对应CacheEntry的索引为ENTRY_METADATA(0)的dirtyfile中。

To measure cache effectiveness, this class tracks three statistics:

public synchronized Snapshot get(String key) throws IOException {

public final class CacheStrategy {

/* The request to send on the network, or null if this call doesn't use the network. /

public final Request networkRequest;

最后再来看Cache.put()办法的return new CacheRequestImpl(editor);:

1.2 Cache-Control

相对值,单位时秒,表示当前资源的有效期。Cache-Control比Expires优先级更高:

合理地利用本地缓存可不需用有效地减少网络开销,减少响应延迟。HTTP报头也定义了好多好多 与缓存有关的域来控制缓存。今天就来讲讲OkHttp中关于缓存要素的实现细节。

既然实际的缓存工作都有在CacheInterceptor中完成的,没办法 接下来看下CahceInterceptor的核心办法intercept办法源码:

If-Modified-Since: Tue, 12 Jan 2016 09:31:27 GMT

可能性当前资源没办法 被二次修改,服务器返回3004告知客户端直接复用本地缓存。

*

CacheStrategy:缓存策略。其内部内部结构维护一一好2个 多 request和response,通过指定request和response来描述是通过网络还是缓存获取response,抑或二者同去使用

private final Runnable cleanupRunnable = new Runnable() {

};

其触发条件在journalRebuildRequired()办法中:

3.7 DiskLruCache.edit

DiskLruCache可不需用看成是Cache在文件系统层的具体实现,好多好多 其基本操作接口居于一一对应的关系:

1.1 Expires

超时时间,一般用在服务器的response报头中用于告知客户端对应资源的过期时间。当客户端需用再次请求相同资源时先比较其过期时间,可能性尚未超过过期时间则直接返回缓存结果,可能性可能性超过则重新请求。

[CacheStrategy$Factory]

3.8总结

总结起来DiskLruCache主要有以下2个特点:

DiskCacheLru初始化时通过读取日志文件创建cache容器:lruEntries。同去通过日志过滤操作不成功的cache项。相关逻辑在DiskLruCache.readJournalLine,DiskLruCache.processJournal

初始化完成后,为除理日志文件不断膨胀,对日志进行重建精简,具体逻辑在DiskLruCache.rebuildJournal

每当有cache操作时将其记录入日志文件中以备下次初始化时使用

当冗余日志太满时,通过调用cleanUpRunnable多线程 重建日志

3.2 DiskLruCache.Entry

每一一好2个 多 DiskLruCache.Entry对应一一好2个 多 cache记录:

Cache:Cache管理器,其内部内部结构含有一一好2个 多 DiskLruCache将cache写入文件系统:

}

3.5 lruEntries

管理cache entry的容器,其数据特性是LinkedHashMap。通过LinkedHashMap一些的实现逻辑达到cache的LRU替换

public final class DiskLruCache implements Closeable, Flushable {

}

核心逻辑都以中文注释的形式在代码中标注出来了,一些人看代码即可。通过底下的代码可不需用看出,几乎所有的动作都有以CacheStrategy缓存策略为办法做出的,没办法 接下来看下缓存策略是如可生成的,相关代码实现在CacheStrategy$Factory.get()办法中:

3.4 SnapShot

cache快照,记录了特定cache在某一一好2个 多 特定时刻的内容。每次向DiskLruCache请求时返回的都有目标cache的一一好2个 多 快照,相关逻辑在DiskLruCache.get中:

final FileSystem fileSystem;

final File directory;

private final File journalFile;

private final File journalFileTmp;

private final File journalFileBackup;

private final int appVersion;

private long maxSize;

final int valueCount;

private long size = 0;

BufferedSink journalWriter;

final LinkedHashMap lruEntries = new LinkedHashMap<>(0, 0.75f, true);

/**

}

一一好2个 多 Entry主要由以下几要素构成:

Last-Modified: Tue, 12 Jan 2016 09:31:27 GMT

当客户端二次请求时,可不需用头部加进如下header:

The best way to improve the cache hit rate is by configuring the web server to return

boolean journalRebuildRequired() {

可不需用看过其核心逻辑在getCandidate函数中。基本要是HTTP缓存协议的实现,核心代码逻辑已通过中文注释说明,一些人直接看代码就好。

}

edit办法返回对应CacheEntry的editor编辑器。接下来再来看下Cache.put()办法的entry.writeTo(editor);,其相关逻辑:

通过LinkedHashMap实现LRU替换

通过本地维护Cache操作日志保证Cache原子性与可用性,同去为除理日志过分膨胀定时执行日志精简

每一一好2个 多 Cache项对应一一好2个 多 情況副本:DIRTY,CLEAN。CLEAN表示当前可用情況Cache,内部内部结构访问到的cache快照均为CLEAN情況;DIRTY为更新态Cache。可能性更新和创建都只操作DIRTY情況副本,实现了Cache的读写分离

每一一好2个 多 Cache项有一好2个 文件,一一好2个 多 情況(DIRTY,CLEAN),每个情況对应一一好2个 多 文件:一一好2个 多 文件存储Cache meta数据,一一好2个 多 文件存储Cache内容数据

Selecting a cache strategy may add conditions to the request (like the "If-Modified-Since"

Cache.get() —>DiskLruCache.get()

Cache.put()—>DiskLruCache.edit() //cache插入

Cache.remove()—>DiskLruCache.remove()

Cache.update()—>DiskLruCache.edit()//cache更新

其中get操作在3.4可能性介绍了,remove操作较为简单,put和update大致逻辑类似,可能性篇幅限制,这里仅介绍Cache.put操作的逻辑,一些的操作一些人看代码就好:

private final class Entry {

[okhttp3.internal.cache.DiskLruCache.java]

public void writeTo(DiskLruCache.Editor editor) throws IOException {

/**

[DiskLruCache.java]

/**

If-None-Match: "5694c7ef-24dc"

可能性文件并未改变,则服务器返回3004告知客户端可不需用复用本地缓存。

/* Used to run 'cleanupRunnable' for journal rebuilds. /

private final Executor executor;

private final Runnable cleanupRunnable = new Runnable() {

key:每个cache都有一一好2个 多 key作为其标识符。当前cache的key为其对应URL的MD5字符串

cleanFiles/dirtyFiles:每一一好2个 多 Entry对应多个文件,其对应的文件数由DiskLruCache.valueCount指定。当前在OkHttp中valueCount为2。即每个cache对应一一好2个 多 cleanFiles,一一好2个 多 dirtyFiles。其中第一一好2个 多 cleanFiles/dirtyFiles记录cache的meta数据(如URL,创建时间,SSL握手记录等等),第一好2个 文件记录cache的真正内容。cleanFiles记录居于稳定情況的cache结果,dirtyFiles记录居于创建或更新情況的cache

currentEditor:entry编辑器,对entry的所有操作都有通过其编辑器完成。编辑器内部内部结构加进了同步锁

3.3 cleanupRunnable

清理多线程 ,用于重建精简日志:

};

...

}

3.1 journalFile

DiskLruCache内部内部结构日志文件,对cache的每一次读写都对应二根日志记录,DiskLruCache通过分析日志分析和创建cache。日志文件格式如下:

[CacheInterceptor.java]

@Override public Response intercept(Chain chain) throws IOException {

// Must be read and written when synchronized on 'this'.

boolean initialized;

boolean closed;

boolean mostRecentTrimFailed;

boolean mostRecentRebuildFailed;

1.5 only-if-cached

只使用缓存

}

其中close,abort办法会调用editor.abort和editor.commit来更新日志,editor.commit前会将dirtyFile重置为cleanFile作为稳定可用的缓存,相关逻辑在okhttp3.internal.cache.DiskLruCache$Editor.completeEdit中:

cacheable responses. Although this client honors all

cache headers, it doesn't cachepartial responses.

/* The cached response to return or validate; or null if this call doesn't use a cache. /

public final Response cacheResponse;

......

}

CacheStrategy$Factory:缓存策略工厂类根据实际请求返回对应的缓存策略

[okhttp3.internal.cache.DiskLruCache$Editor.completeEdit]

synchronized void completeEdit(Editor editor, boolean success) throws IOException {

1.3.2 ETag

ETag是对资源文件的一些摘要,可不需用通过ETag值来判断文件有无 有修改。当客户端第一次请求某资源时,服务器返回:

日志文件的应用场景主要有一好2个 :

[okhttp3.internal.cache.DiskLruCache.java]

synchronized Editor edit(String key, long expectedSequenceNumber) throws IOException {

[CacheStrategy.java]

/**

private long nextSequenceNumber = 0;

}

CacheRequestImpl实现CacheRequest接口,向内部内部结构类(主要是CacheInterceptor)透出,内部内部结构对象通过CacheRequestImpl更新或写入缓存数据。

}

可不需用看过核心逻辑在editor = cache.edit(key(response.request().url()));,相关代码在DiskLruCache.edit:

*Sometimes a request will result in a conditional cache hit. If the cache contains a stale copy ofthe response, the client will issue a conditional {@code GET}. The server will then send eitherthe updated response if it has changed, or a short 'not modified' response if the client's copyis still valid. Such responses increment both the network count and hit count.

[okhttp3.Cache.java]

CacheRequest put(Response response) {

作者:李牙刷儿

原文链接:https://www.jianshu.com/p/87da91631a70

data-url="http://tools.ietf.org/html/rfc7234">

Cache-Control:max-age=315330000,public

1.3 条件GET请求

1.3.1 Last-Modified-Date

客户端第一次请求时,服务器返回:

[okhttp3.Cache$CacheRequestImpl]

private final class CacheRequestImpl implements CacheRequest {

Cache内部内部结构通过requestCount,networkCount,hitCount一一好2个 多 统计指标来优化缓存波特率

}

当冗余日志超过日志文件一些的一般且总条数超过30000时执行

3.6 FileSystem

使用Okio对File的封装,繁复了I/O操作。

1.4 no-cache/no-store

不使用缓存