邮箱:oxwangfeng@qq.com
分类: 架构设计与优化
2016-03-16 20:12:19
合并回源流程如下:
1.对于同一个URL请求,如果当前已经有请求A回源了,那么后续请求B首先读取已回源请求A的内容
2.当请求A由于种种问题(例如网络不好)没有在500ms内拉回响应,那么请求B判断本地是否有对应副本(肯定是已过期的副本,否则A就不会回源>了)
3.请求B通过索引判断本地是否有副本:如果副本有对应的索引,则试图读取本地内容(先是mem,再disk);如果本地没有副本对应的索引,则直>接走proxy_only(回源但不缓存副本)流程
4.如果在读取本地副本的所有流程中出现任何error(包括,mem不可用,disk不可用等等,内容头magic有问题等等),直接走proxy_only流程
5.如果读取本地副本没有任何问题,那么在响应ua的header中,加上一个113的status code(Warning),表示读取本地过期缓存
Patch主要程序分析:
1. int ret = openReadChooseWriter(event, e);
如果ret == EVENT_CONT,表示现在已经有writer,但是没有合法的副本;
修改前:
修改后:
解析:
解析1.
首先解释两个函数,VC_SCHED_WRITER_RETRY()是修改前用的函数;VC_SCHED_WRITER_COUNT_RETRY()是修改后使用的函数;并且WRITER_RETRY_DELAY:50ms;
VC_SCHED_WRITER_RETRY:意思是每try一次,都会在_t时间后状态机返回EVENT_CONT;在ret ==
EVENT_CONT后调用VC_SCHED_WRITER_RETRY函数,表示已经有writes了,会一直等待合法的副本;
#define VC_SCHED_WRITER_RETRY() \
do
{ \
ink_assert(!trigger); \
writer_lock_retry++; \
ink_hrtime _t = WRITER_RETRY_DELAY; \
if (writer_lock_retry > 2) \
_t = WRITER_RETRY_DELAY * 2; \
else if (writer_lock_retry > 5) \
_t = WRITER_RETRY_DELAY * 10; \
else if (writer_lock_retry > 10) \
_t = WRITER_RETRY_DELAY * 100; \
trigger = mutex->thread_holding->schedule_in_local(this, _t); \
return EVENT_CONT; \
}
while (0)
VC_SCHED_WRITER_COUNT_RETRY:只要尝试次数小于8,则每次_t都会延长一倍,并且会在_t时间后状态机返回EVENT_CONT;并且尝试次数大于等于8,则不尝试了;
+#define VC_SCHED_WRITER_COUNT_RETRY() \
+ do
{ \
+
ink_assert(!trigger); \
+
writer_lock_retry++; \
+
ink_hrtime _t = WRITER_RETRY_DELAY; \
+
if (writer_lock_retry > 2) \
+
_t = WRITER_RETRY_DELAY * 2; \
+
if (writer_lock_retry < 8) { \
+
trigger = mutex->thread_holding->schedule_in_local(this, _t); \
+
return EVENT_CONT; \
+
} else { \
+
\
+
} \
+ }
while (0)
+
解析2:
当超过尝试次数以后,就会设置is_retry_count_exceeded = true;如果slow_os_use_stale为true,则通知状态机回调CacheVC::openReadStartHead;
解析3:
2.由于返回的是旧的数据,所以http打了一个warnning的头部;User-Agent:jddebug会打出相应的debug信息