Chinaunix首页 | 论坛 | 博客
  • 博客访问: 146880
  • 博文数量: 12
  • 博客积分: 2069
  • 博客等级: 大尉
  • 技术积分: 257
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-16 13:29
文章分类

全部博文(12)

文章存档

2012年(5)

2011年(2)

2010年(4)

2008年(1)

分类: 系统运维

2012-07-05 16:43:22

用户带宽突飞猛进,视频网站铺天盖地,我们公司也耐不住寂寞,加入视频点播的行列大军中。技术很简单,flash播放器+http半下载+mp4视频源。为了支持start和end标签,我们用了一个三方nginx模块: 。一直运行很正常。

突然昨天收到cdn报障,说有一个视频文件下载过程中总是不能下载完全。手工用curl -vo /dev/null -x IP:80 测试,果然视频下载过程中会中断,而且中断时间和大小不等。

因为使用了LVS,首先排除它的影响,直接指定LVS后端real server的IP,测试结果同使用LVS,排除LVS的问题。
查看源站nginx的log,我去,大量的segment fault的报错信息,nginx被干掉,难怪下不完。
我们同时还有一台服务器虽然不提供线上服务,但所有的数据和服务都是可用的,测试使用此服务器访问同样的文件,完全下载,于是认为只要找到此两个服务器之间服务的区别就OK了(后边会发现这个决定有多错误)。仔细对比此两个服务器,除了java一个用的是官方的,一个时openjdk之外,没有任何区别。把出错服务器的java替换为javaTM版,测试,结果,还是不行。
看来真不能不知其所以然的绕过去,只好一步步debug了。先把系统的core dump打开(此处记着一定要让core dump的目录出错进程有写权限,我找这个问题用了很长时间):

点击(此处)折叠或打开

  1. ulimit -c unlimited
  2. chown web:web /home/nginx/sbin/
  3. /home/nginx/sbin/nginx -s stop && /home/nginx/sbin/nginx
core文件瀑布似的就把我的目录充满了,赶紧先把core dump 关掉。用gdb查core文件信息:

点击(此处)折叠或打开

  1. (gdb) bt
  2. #0 0x00007f7d3073e1b5 in raise () from /lib/libc.so.6
  3. #1 0x00007f7d30740fc0 in abort () from /lib/libc.so.6
  4. #2 0x00007f7d3077437b in ?? () from /lib/libc.so.6
  5. #3 0x00007f7d3077dbd6 in ?? () from /lib/libc.so.6
  6. #4 0x00007f7d3078294c in free () from /lib/libc.so.6
  7. #5 0x00007f7d3076eb1d in fclose () from /lib/libc.so.6
  8. #6 0x00000000004a1d84 in mp4_context_exit (mp4_context=0x1425620) at ../nginx_mod_h264_streaming-2.2.7/src/mp4_io.c:548
  9. #7 0x00000000004a209f in mp4_open (
  10.     filename=0x14440e9 <optimized output>, filesize=10403840, flags=MP4_OPEN_ALL, verbose=0) at ../nginx_mod_h264_streaming-2.2.7/src/mp4_io.c:623
  11. #8 0x000000000049f623 in mp4_process (
  12.     filename=0x14440e9 <optimized output>, filesize=10403840, verbose=0, buckets=0x7fffe364fa38, options=0x1425590) at ../nginx_mod_h264_streaming-2.2.7/src/mp4_process.c:146
  13. #9 0x000000000049fb97 in ngx_streaming_handler (r=0x1439760) at ../nginx_mod_h264_streaming-2.2.7/src/ngx_http_streaming_module.c:297
  14. #10 0x000000000043c8e3 in ngx_http_core_content_phase (r=0x1439760, ph=0x1456388) at src/http/ngx_http_core_module.c:1339
  15. #11 0x000000000043b510 in ngx_http_core_run_phases (r=0x1439760) at src/http/ngx_http_core_module.c:837
  16. #12 0x000000000043b487 in ngx_http_handler (r=0x1439760) at src/http/ngx_http_core_module.c:820
  17. #13 0x0000000000448255 in ngx_http_process_request (r=0x1439760) at src/http/ngx_http_request.c:1650
  18. #14 0x0000000000446d4c in ngx_http_process_request_headers (rev=0x14867d0) at src/http/ngx_http_request.c:1093
  19. #15 0x000000000044653b in ngx_http_process_request_line (rev=0x14867d0) at src/http/ngx_http_request.c:893
  20. #16 0x0000000000445ce3 in ngx_http_init_request (rev=0x14867d0) at src/http/ngx_http_request.c:518
  21. #17 0x00000000004288bd in ngx_event_process_posted (cycle=0x14259c0, posted=0x6de758) at src/event/ngx_event_posted.c:39
  22. #18 0x00000000004267e4 in ngx_process_events_and_timers (cycle=0x14259c0) at src/event/ngx_event.c:272
  23. #19 0x0000000000433223 in ngx_worker_process_cycle (cycle=0x14259c0, data=0x0) at src/os/unix/ngx_process_cycle.c:800
  24. #20 0x000000000042fd66 in ngx_spawn_process (cycle=0x14259c0, proc=0x433089 <ngx_worker_process_cycle>, data=0x0,
  25.     name=0x4b29bb "worker process", respawn=-3) at src/os/unix/ngx_process.c:196
  26. #21 0x00000000004320bd in ngx_start_worker_processes (cycle=0x14259c0, n=8, type=-3) at src/os/unix/ngx_process_cycle.c:360
  27. #22 0x000000000043172c in ngx_master_process_cycle (cycle=0x14259c0) at src/os/unix/ngx_process_cycle.c:136
  28. #23 0x0000000000403fdd in main (argc=1, argv=0x7fffe3650448) at src/core/nginx.c:405
试了几个core文件,发现所有文件filesize都是一样的,而且问题发生在mp4_open这个过程,突然想,不会是某一个文件故障造成nginx崩溃,而事实上跟我收到报障的文件没关系吧?赶紧又测了另外几个大文件,果然,其他文件也出现错误,而且每次测试的频率不等。
正在以为问题解决时,发现为什么filename那项是?google大神才发现,原来是 gcc -O 作祟,这个就简单了,把源码重新configure一遍,然后把objs/Makefile里面 CFLAGS的 -O参数去除。
再调试,文件名出来了。用ffmpeg -i 跑一下:

点击(此处)折叠或打开

  1. ffmpeg -i E84IE281L-mobile.mp4.des
  2. FFmpeg version SVN-r25741, Copyright (c) 2000-2010 the FFmpeg developers
  3. built on Apr 11 2011 09:30:23 with gcc 4.3.2
  4. configuration: --prefix=/usr --enable-gpl --enable-shared --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libvorbis --enable-libxvid --enable-postproc --enable-libfaac --enable-libx264 --enable-pthreads --enable-nonfree --enable-version3
  5. libavutil 50.33. 0 / 50.33. 0
  6. libavcore 0.12. 1 / 0.12. 1
  7. libavcodec 52.94. 4 / 52.94. 4
  8. libavformat 52.84. 0 / 52.84. 0
  9. libavdevice 52. 2. 2 / 52. 2. 2
  10. libavfilter 1.62. 0 / 1.62. 0
  11. libswscale 0.12. 0 / 0.12. 0
  12. libpostproc 51. 2. 0 / 51. 2. 0
  13. [mov,mp4,m4a,3gp,3g2,mj2 @ 0x25004c0] error reading header: -1
  14. E84IE281L-mobile.mp4.des: Operation not permitted
文件的header被破坏了。再查core文件的堆栈,错误发生在mp4_context_exit阶段,双重fclose了。往上追一点代码,果然read_box在读取文件失败时调用了fclose()。其实这个fclose是没有必要的,因为出错都是要mp4_context_exit收尾的,所以完全可以不用处理。把这行注释掉:

点击(此处)折叠或打开

  1. diff nginx_mod_h264_streaming-2.2.7/src/mp4_io.c nginx_mod_h264_streaming-2.2.7.fix/src/mp4_io.c
  2. 515,517c515
  3. < /* This close action should be completed in the mp4_context_exit function
  4. < fclose(infile);
  5. < */
  6. ---
  7. > fclose(infile);
重新编译,果然一切OK,收关。
阅读(4106) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~