Chinaunix首页 | 论坛 | 博客
  • 博客访问: 432836
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 518
  • 用 户 组: 普通用户
  • 注册时间: 2015-12-14 12:10
个人简介

邮箱:oxwangfeng@qq.com

文章分类

全部博文(43)

文章存档

2021年(1)

2018年(7)

2017年(9)

2016年(26)

我的朋友

分类: 云计算

2016-01-15 19:35:37

目录

object乱码           
    描述                   
    问题跟踪              
主页乱码180s超时 
    描述                     
    问题跟踪                 
        Ats设置cache头部资源不可信 
        乱码出现active timeout原因 
问题解决方案                 

主页乱码包括两个现象,一个是出现object乱码,一个是超过active timeout后连接才关闭,两者是同时出现的;下面分别介绍这两个问题。

object乱码

描述

客户端从ATS请求object,未命中需回源,源站object进行gzip压缩传输,ats缓存对象响应客户端;然后,源站object资源清空;客户端再次请求ats拉取object,未命中回源,这次object为空,更新缓存;这时,客户端再次请求ats拉取object,出现乱码。


问题跟踪

乱码的没有经过openWriteMain,也就是没有将数据data写入cache

跟踪vc->f.rewrite_resident_alt=true

初始化情况下od->move_resident_alt =1.只有当304状态下才设置为0。但是在更新doc为空(total_len=0)情况下,又重新设置od->move_resident_alt = 1.所以这儿需要修改的是在content length=0的情况下,将od->move_resident_alt = 0;


CacheVC::updateVector(int /* event ATS_UNUSED */, Event */* e ATS_UNUSED */)

{

     //正常情况下

      if (update_key == od->single_doc_key && (total_len || !vec))

        od->move_resident_alt = 0;


    //当是乱码的时候od->move_resident_alt=1

if (od->move_resident_alt && first_buf._ptr() && !od->has_multiple_writers()) {

      if (small_doc && have_res_alt && (fragment || (f.update && !total_len))) {

                   f.rewrite_resident_alt = 1;

      }

}

}


2.将以前cachedata copy到新的cache buffer

将原来cache的内容copy到buffer中,由于以前cache的data是gzip压缩的,而这次header是非gzip压缩,所以导致了乱码;

Proxy/http/CacheWrite.cc    

static int

agg_copy(char *p, CacheVC *vc)//VolHeaderFooter

{

#ifdef HTTP_CACHE

if (vc->f.rewrite_resident_alt)

        iobufferblock_memcpy(doc->data(), vc->write_len, res_alt_blk, 0);

      else

#endif

        iobufferblock_memcpy(doc->data(), vc->write_len, vc->blocks, vc->offset);

}


主页乱码180s超时

描述

上一个问题描述出现后,这时空object已经缓存,再次访问对象状态是cHs f命中。虽然object乱码立即返回,但是ats后台这次object访问连接没有释放,即HttpClientSession没有释放。就会发生180s超时后,连接关闭。超时时间配置文件可配置。


问题跟踪

Ats设置cache头部资源不可信

导致s->hdr_info.trust_response_cl 设置为false,即设置头部信息不可信:

当http访问命中缓存后,发现头部content-length的大小和cache object的size大小不一样的时候,设置s->hdr_info.trust_response_cl = false;

s->cache_info.object_read->object_size_get()和base->get_content_length() 两者大小不一样;

void

HttpTransact::handle_content_length_header(State* s, HTTPHdr* header, HTTPHdr* base)

{

          DebugTxn("http_trans", "Content Length header and cache object size mismatch." "Disabling keep-alive");

          s->hdr_info.trust_response_cl = false;

}


导致receive_chunked_response设置为true

当cache的头部信息为不可信的时候, receive_chunked_response = true;当设置为不可信后,如果头部包含content-length,则删除;

void

HttpTransact::handle_response_keep_alive_headers(State* s, HTTPVersion ver, HTTPHdr* heads)

{

If(…. || s->hdr_info.trust_response_cl == false))  || …)

{

s->client_info.receive_chunked_response = true;

}

//make sure no content length header is send when transfer encoding is chunked

    if ( s->client_info.receive_chunked_response ) {

      s->hdr_info.trust_response_cl = false;


      // And delete the header if it's already been added...

      heads->field_delete(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);

}

….

}


导致HttpTunnelProducer.chunking_action= TCA_CHUNK_CONTENT

由于receive_chunked_response设置为true,导致HttpTunnelProducer.chunking_action= TCA_CHUNK_CONTENT


HttpSM::setup_cache_read_transfer()

{

  if ( t_state.client_info.receive_chunked_response ) {

   tunnel.set_producer_chunking_action(p,client_response_hdr_bytes,TCA_CHUNK_CONTENT);

    tunnel.set_producer_chunking_size(p, t_state.txn_conf->http_chunking_size);

  }

}

乱码出现active timeout原因

由于action为TCA_CHUNK_CONTENT,触发了p->do_chunking = true,进而设置c_write = INT64_MAX;然后在do_io_write中将往client net io写的字节数设置为INT64_MAX;在发送给client的过程中, 由于producer产生的object大小和消费者认为的大小不一致,所以event设置为VC_EVENT_WRITE_READY;所以一直处于ready状态,直到active timeout,连接关闭;


设置vio.nbytes= INT64_MAX

Proxy/http/HttpTunnel.cc

HttpTunnel::producer_run(HttpTunnelProducer * p)

由于触发了如下代码:

if (action == TCA_CHUNK_CONTENT)

      p->do_chunking = true;

… p855

    if (p->do_chunking == true) {

      c_write = INT64_MAX;

}

然后调用

c->vc->do_io_write(this, c_write, c->buffer_reader);

调用iocache/cache/Cache.cc:

VIO *

CacheVC::do_io_write(Continuation *c, int64_t nbytes, IOBufferReader *abuf, bool owner)

{

//此处将vio的nbytes即往client net io写的字节数设置为INT64_MAX

vio.nbytes = nbytes;

}


设置event VC_EVENT_WRITE_READY

….

然后调用UnixNetVConnection.cc:

void

write_to_net_io(NetHandler *nh, UnixNetVConnection *vc, EThread *thread)

{

….

/*

 ntodo=9223372036854775807,towrite=448..

*/

  // signal write ready to allow user to fill the buffer

  if (towrite != ntodo && buf.writer()->write_avail()) {

    //由于producer产生的object大小和消费者认为的大小不一致,所以event设置为VC_EVENT_WRITE_READY

    if (write_signal_and_update(VC_EVENT_WRITE_READY, vc) != EVENT_CONT) {

      return;

    }

….

  //这个函数就是往fd里面发送数据了;

  int64_t r = vc->load_buffer_and_write(towrite, wattempted, total_wrote, buf, needs);

}


导致active timeout

当状态为VC_EVENT_WRITE_READY时,启动消费者,启动write vio;也就是一直等待生产者往buffer里面填充数据;当等待超过active timeout的时候,就会触发VC_EVENT_INACTIVITY_TIMEOUT事件;

VC_EVENT_WRITE_READY:

  case VC_EVENT_WRITE_READY:

    this->consumer_reenable(c);

    break;


  case VC_EVENT_WRITE_READY:

    server_entry->write_vio->reenable();

    break;


断开连接:

当event为VC_EVENT_INACTIVITY_TIME


问题解决方案


方案:网页出现乱码的根本原因是doc header中的content lengthdoc body中的实际长度不一致导致的,解决这个问题的关键是让doc header中的content lengthdoc body一致。

解决方法:

1.      当从二级cache接受到的headercontent length=0,设置一个标志位flag=true

2.      当写cache的时候,if flag = true,则doc data部分可以设置为null(即不往docdata部分写数据);





阅读(4515) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:cdn流量调度系统

给主人留下些什么吧!~~