因/synchrony-proxy/resources/js/vendor/sockjs.min.js等502 Bad Gateway加载不出来,导致无法使用编辑页的解决方法:关闭掉Synchrony proxy即可。

具体方法:
1. 编辑<home-directory>/confluence.cfg.xml

    <property name="synchrony.proxy.enabled">true</property>

修改为

    <property name="synchrony.proxy.enabled">false</property> 

2. 重启Confluence。

背景

当今互联网,数据呈现爆炸式增长,社交网络、移动通信、网络视频、电子商务等各种应用往往能产生亿级甚至十亿、百亿级的海量小文件。由于在元数据管理、访问性能、存储效率等方面面临巨大的挑战,海量小文件问题成为了业界公认的难题。

业界的一些知名互联网公司,也对海量小文件提出了解决方案,例如:著名的社交网站Facebook,存储了超过600亿张图片,专门推出了Haystack系统,针对海量小图片进行定制优化的存储。

白山云存储CWN-X针对小文件问题,也推出独有的解决方案,我们称之为Haystack_plus。该系统提供高性能数据读写、数据快速恢复、定期重组合并等功能。

Facebook的Haystack

Facebook的Haystack对小文件的解决办法是合并小文件。将小文件数据依次追加到数据文件中,并且生成索引文件,通过索引来查找小文件在数据文件中的offset和size,对文件进行读取。

Haystack的数据文件部分

Haystack的数据文件,将每个小文件封装成一个needle,包含文件的key、size、data等数据信息。所有小文件按写入的先后顺序追加到数据文件中。

Haystack的索引文件部分

Haystack的索引文件保存每个needle的key,以及该needle在数据文件中的offset、size等信息。程序启动时会将索引加载到内存中,在内存中通过查找索引,来定位在数据文件中的偏移量和大小。

Haystack面临的问题

Facebook的Haystack特点是将文件的完整key都加载到内存中,进行文件定位。机器内存足够大的情况下,Facebook完整的8字节key可以全部加载到内存中。

但是现实环境下有两个主要问题:

  1. 存储服务器内存不会太大,一般为32G至64G;
  2. 小文件对应的key大小难控制,一般选择文件内容的MD5或SHA1作为该文件的key。

场景举例

  • 一台存储服务器有12块4T磁盘,内存为32GB左右。
  • 服务器上现需存储大小约为4K的头像、缩略图等文件,约为10亿个。
  • 文件的key使用MD5,加上offset和size字段,平均一个小文件对应的索引信息占用28字节。
  • 在这种情况下,索引占用内存接近30GB,磁盘仅占用4TB。内存消耗近100%,磁盘消耗只有8%。

所以索引优化是一个必须要解决的问题。

Haystack_plus

Haystack_plus的核心也由数据文件和索引文件组成。

1. Haystack_plus的数据文件

与Facebook的Haystack类似,Haystack_plus将多个小文件写入到一个数据文件中,每个needle保存key、size、data等信息。

2. Haystack_plus的索引文件

索引是我们主要优化的方向:

  • 索引文件只保存key的前四字节,而非完整的key;
  • 索引文件中的offset和size字段,通过512字节对齐,节省1个字节;并根据整个Haystack_plus数据文件实际大小计算offset和size使用的字节数。

3. Haystack_plus的不同之处

数据文件中的needle按照key的字母顺序存放。

由于索引文件的key,只保存前四字节,如果小文件key的前四字节相同,不顺序存放,就无法找到key的具体位置。可能出现如下情况:

例如:用户读取的文件key是0x ab cd ef ac ee,但由于索引文件中的key只保存前四字节,只能匹配0x ab cd ef ac这个前缀,此时无法定位到具体要读取的offset。

我们可以通过needle顺序存放,来解决这个问题:

例如:用户读取文件的key是0x ab cd ef ac bb,匹配到0x ab cd ef ac这个前缀,此时offset指向0x ab cd ef ac aa这个needle,第一次匹配未命中。

通过存放在needle header中的size,我们可以定位0x ab cd ef ac bb位置,匹配到正确needle,并将数据读取给用户。

4. 索引搜索流程为

5. 请求不存在的文件

问题:我们应用折半查找算法在内存查找key,时间复杂度为O(log(n)),其中n为needle数目。索引前缀相同时,需要在数据文件中继续查找。此时访问的文件不存在时,容易造成多次IO查找。

解决方法:在内存中,将存在的文件映射到bloom filter中。此时只需要通过快速搜索,就可以排除不存在的文件。

时间复杂度为O(k),k为一个元素需要的bit位数。当k为9.6时,误报率为1%,如果k再增加4.8,误报率将降低为0.1%。

6. 前缀压缩,效果如何

Haystack_plus与Facebook Haystack内存消耗的对比,场景举例,文件(如:头像、缩略图等)大小4K,key为MD5:

内存消耗对比

Key

offset

size

Haystack

全量key,16字节

8字节

4字节

Haystack_plus

4字节

4字节

1字节

注:Haystack的needle为追加写入,因此offset和size大小固定。Haystack_plus的key使用其前4字节,offset根据Haystack_plus数据文件的地址空间计算字节数,并按512字节对齐;size根据实际文件的大小计算字节数,并按512对齐。

从上图可以看出在文件数量为10亿的情况下,使用Facabook的Haystack消耗的内存超过26G,使用Haystack_plus仅消耗9G多内存,内存使用降低了2/3。

7.索引优化根本就停不下来

10亿个4K小文件,消耗内存超过9G。Key占用4字节,Offset占用4字节,还需要再小一些。

索引分层

根据文件key的前缀,进行分层,相同的前缀为一层。

分层的好处

减少key的字节数

通过分层,只保存一份重复的前缀,节省key的字节数。

减少offset的字节数

优化前的offset,偏移范围为整个Haystack_plus的数据文件的地址空间。

优化后,只需在数据文件中的层内进行偏移,根据最大的层地址空间可以计算所需字节数。

分层后的效果

从上图可以看出,进行分层后,内存消耗从优化前的9G多,降低到4G多,节省了一半的内存消耗。

Haystack_plus整体架构

1. Haystack_plus组织

每台服务器上,我们将所有文件分成多个group,每个group创建一个Haystack_plus。系统对所有的Haystack_plus进行统一管理。

读、写、删除等操作,都会在系统中定位操作某个Haystack_plus,然后通过索引定位具体的needle,进行操作。

2. 索引组织

之前已经介绍过,所有needle顺序存放,索引做前缀压缩,并分层。

3. 文件组成

  • chunk文件:小文件的实际数据被拆分保存在固定数量的chunk数据文件中,默认为12个数据块;
  • needle list文件:保存每个needle的信息(如文件名、offset等);
  • needle index和layer index文件:保存needle list在内存中的索引信息;
  • global version文件:保存版本信息,创建新version时自动将新版本信息追加到该文件中;
  • attribute文件:保存系统的属性信息(如chunk的SHA1等);
  • original filenames:保存所有文件原始文件名。

A、Haystack_plus数据文件被拆分为多个chunk组织,chunk1,chunk2,chunk3……

B、分成多个chunk的好处:

1. 数据损坏时,不影响其它chunk的数据;

2. 数据恢复时,只需恢复损坏的chunk。

C、每个chunk的SHA1值存放在attribute文件中。

4. 版本控制

由于needle在数据文件中按key有序存放,为不影响其顺序,新上传的文件无法加入Haystack_plus,而是首先被保存到hash目录下,再通过定期自动合并方式,将新文件加入到Haystack_plus中。

合并时将从needle_list文件中读取所有needle信息,将删除的needle剔除,并加入新上传的文件,同时重新排序,生成chunk数据文件、索引文件等。

重新合并时将生成一个新版本Haystack_plus。版本名称是所有用户的文件名排序的SHA1值的前4字节。

每半个月系统自动进行一次hash目录检查,查看是否有新文件,并计算下所有文件名集合的SHA1,查看与当前版本号是否相同,不同时说明有新文件上传,系统将重新合并生成新的数据文件。

同时,系统允许在hash目录下超过指定的文件数时,再重新创建新版本,从而减少重新合并次数。

版本的控制记录在global_version文件中,每次创建一个新版本,版本号和对应的crc32将追加到global_version文件(crc32用于查看版本号是否损坏)。

每次生成新版本时,自动通知程序重新载入索引文件、attribute文件等。

5. 数据恢复

用户的文件将保存成三副本存放,因此Haystack_plus也会存放在3台不同的机器上。

恢复场景一

当一个Haystack_plus的文件损坏时,会在副本机器上,查找是否有相同版本的Haystack_plus,如果版本相同,说明文件的内容都是一致,此时只需将要恢复的文件从副本机器下载下来,进行替换。

恢复场景二

如果副本机器没有相同版本的Haystack_plus,但存在更高版本,那此时可以将该版本的整个Haystack_plus从副本机器上拷贝下来,进行替换。

恢复场景三

如果前两种情况都不匹配,那就从另外两台副本机器上,将所有文件都读到本地上的hash目录下,并将未损坏的chunk中保存的文件也提取到hash目录下,用所有文件重新生成新版本的Haystack_plus。

Haystack_plus效果如何

在使用Haystack_plus后一段时间,我们发现小文件的整体性能有显著提高,RPS提升一倍多,机器的IO使用率减少了将近一倍。同时,因为优化了最小存储单元,碎片降低80%。

使用该系统我们可以为用户提供更快速地读写服务,并且节省了集群的资源消耗。

Link: http://www.infoq.com/cn/articles/solution-of-massive-small-files

形式

#include <sys/ptrace.h>

int ptrace(int request, int pid, int addr, int data);

描述

Ptrace 提供了一种父进程可以控制子进程运行,并可以检查和改变它的核心image。它主要用于实现断点调试。一个被跟踪的进程运行中,直到发生一个信号。则进程被中止,并且通知其父进程。在进程中止的状态下,进程的内存空间可以被读写。父进程还可以使子进程继续执行,并选择是否是否忽略引起中止的信号。

Request参数决定了系统调用的功能:

PTRACE_TRACEME

本进程被其父进程所跟踪。其父进程应该希望跟踪子进程。

PTRACE_PEEKTEXT, PTRACE_PEEKDATA

从内存地址中读取一个字节,内存地址由addr给出。

PTRACE_PEEKUSR

从USER区域中读取一个字节,偏移量为addr。

PTRACE_POKETEXT, PTRACE_POKEDATA

往内存地址中写入一个字节。内存地址由addr给出。

PTRACE_POKEUSR

往USER区域中写入一个字节。偏移量为addr。

PTRACE_SYSCALL, PTRACE_CONT

重新运行。

PTRACE_KILL

杀掉子进程,使它退出。

PTRACE_SINGLESTEP

设置单步执行标志

PTRACE_ATTACH

跟踪指定pid 进程。

PTRACE_DETACH

结束跟踪

Intel386特有:

PTRACE_GETREGS

读取寄存器

PTRACE_SETREGS

设置寄存器

PTRACE_GETFPREGS

读取浮点寄存器

PTRACE_SETFPREGS

设置浮点寄存器

init进程不可以使用此函数

返回值

成功返回0。错误返回-1。errno被设置。

错误

EPERM

特殊进程不可以被跟踪或进程已经被跟踪。

ESRCH

指定的进程不存在

EIO

请求非法

ptrace系统函数。 ptrace提供了一种使父进程得以监视和控制其它进程的方式,它还能够改变子进程中的寄存器和内核映像,因而可以实现断点调试和系统调用的跟踪。使用ptrace,你可以在用户层拦截和修改系统调用(sys call).

功能详细描述

1)   PTRACE_TRACEME

形式:ptrace(PTRACE_TRACEME,0 ,0 ,0)

描述:本进程被其父进程所跟踪。其父进程应该希望跟踪子进程。

2)  PTRACE_PEEKTEXT, PTRACE_PEEKDATA

形式:ptrace(PTRACE_PEEKTEXT, pid, addr, data)

        ptrace(PTRACE_PEEKDATA, pid, addr, data)

描述:从内存地址中读取一个字节,pid表示被跟踪的子进程,内存地址由addr给出,data为用户变量地址用于返回读到的数据。在Linux(i386)中用户代码段与用户数据段重合所以读取代码段和数据段数据处理是一样的。

3)  PTRACE_POKETEXT, PTRACE_POKEDATA

形式:ptrace(PTRACE_POKETEXT, pid, addr, data)

        ptrace(PTRACE_POKEDATA, pid, addr, data)

描述:往内存地址中写入一个字节。pid表示被跟踪的子进程,内存地址由addr给出,data为所要写入的数据。

4)  TRACE_PEEKUSR

形式:ptrace(PTRACE_PEEKUSR, pid, addr, data)

描述:从USER区域中读取一个字节,pid表示被跟踪的子进程,USER区域地址由addr给出,data为用户变量地址用于返回读到的数据。USER结构为core文件的前面一部分,它描述了进程中止时的一些状态,如:寄存器值,代码、数据段大小,代码、数据段开始地址等。在Linux(i386)中通过PTRACE_PEEKUSER和PTRACE_POKEUSR可以访问USER结构的数据有寄存器和调试寄存器。

5)  PTRACE_POKEUSR

形式:ptrace(PTRACE_POKEUSR, pid, addr, data)

描述:往USER区域中写入一个字节,pid表示被跟踪的子进程,USER区域地址由addr给出,data为需写入的数据。

6)   PTRACE_CONT

形式:ptrace(PTRACE_CONT, pid, 0, signal)

描述:继续执行。pid表示被跟踪的子进程,signal为0则忽略引起调试进程中止的信号,若不为0则继续处理信号signal。

7)  PTRACE_SYSCALL

形式:ptrace(PTRACE_SYS, pid, 0, signal)

描述:继续执行。pid表示被跟踪的子进程,signal为0则忽略引起调试进程中止的信号,若不为0则继续处理信号signal。与PTRACE_CONT不同的是进行系统调用跟踪。在被跟踪进程继续运行直到调用系统调用开始或结束时,被跟踪进程被中止,并通知父进程。

8)   PTRACE_KILL

形式:ptrace(PTRACE_KILL,pid)

描述:杀掉子进程,使它退出。pid表示被跟踪的子进程。

9)   PTRACE_SINGLESTEP

形式:ptrace(PTRACE_KILL, pid, 0, signle)

描述:设置单步执行标志,单步执行一条指令。pid表示被跟踪的子进程。signal为0则忽略引起调试进程中止的信号,若不为0则继续处理信号signal。当被跟踪进程单步执行完一个指令后,被跟踪进程被中止,并通知父进程。

10)  PTRACE_ATTACH

形式:ptrace(PTRACE_ATTACH,pid)

描述:跟踪指定pid 进程。pid表示被跟踪进程。被跟踪进程将成为当前进程的子进程,并进入中止状态。

11)  PTRACE_DETACH

形式:ptrace(PTRACE_DETACH,pid)

描述:结束跟踪。 pid表示被跟踪的子进程。结束跟踪后被跟踪进程将继续执行。

12)  PTRACE_GETREGS

形式:ptrace(PTRACE_GETREGS, pid, 0, data)

描述:读取寄存器值,pid表示被跟踪的子进程,data为用户变量地址用于返回读到的数据。此功能将读取所有17个基本寄存器的值。

13)  PTRACE_SETREGS

形式:ptrace(PTRACE_SETREGS, pid, 0, data)

描述:设置寄存器值,pid表示被跟踪的子进程,data为用户数据地址。此功能将设置所有17个基本寄存器的值。

14)  PTRACE_GETFPREGS

形式:ptrace(PTRACE_GETFPREGS, pid, 0, data)

描述:读取浮点寄存器值,pid表示被跟踪的子进程,data为用户变量地址用于返回读到的数据。此功能将读取所有浮点协处理器387的所有寄存器的值。

15)  PTRACE_SETFPREGS

形式:ptrace(PTRACE_SETREGS, pid, 0, data)

描述:设置浮点寄存器值,pid表示被跟踪的子进程,data为用户数据地址。此功能将设置所有浮点协处理器387的所有寄存器的值。

 

link: http://blog.sina.com.cn/s/blog_4ac74e9a0100n7w1.html

首先从整体上介绍git服务器的工作原理:多个客户端,其中可以包括仓库管理员,通过将自己的ssh公钥上传到服务器仓库keydir目录,统一调用Git专用账号git进行访问git仓库,不同的用户可以根据不同的ssh公钥校验登录,进行项目版本的各种操作,包括clone,commit,push,pull等等。
    下面具体介绍Git服务器的搭建,机器环境:ubuntu12.04,Git服务器软件采用gitosis(https://github.com/res0nat0r/gitosis ,网上很多文章给的地址根本无法使用,都是copy的,不给力啊! )。
一、软件安装
    1.1 安装ssh的服务端和客户端:sudo apt-get install openssh-server openssh-client
    1.2 安装git-core软件,这个是git服务的基础:sudo apt-get install git-core
    1.3 安装 Gitosis,这个是git服务器软件

de>sudo apt-get install python-setuptoolsde>de>
de>de>cd /tmp
de>de>git clone https://github.com/res0nat0r/gitosis.git
de>de>
de>de>cd gitosisde>

sudo python setup.py install 

 

    ok,软件的安装都此结束。
 
二、创建Git专用账号git
    sudo useradd -m -s /bin/bash git    //创建git账号,用户家目录默认为/home/git,shell为/bin/bash
    sudo passwd git    //设置git用户的密码
 
三、初始化Git仓库
    1、初始化Git仓库需要一个管理员账号,如上图所示,管理员也是一个客户端用户,所以需要在客户端主机(我的客户端机器是Win7系统)生成一个用户,并且生成ssh-key。具体操作如下:
        
        在客户端安装ssh服务,包括客户端和服务端。如果你的客户端系统是:
            (1)Windows机器,建议直接安装git bash软件,其中包括了ssh这个服务;
            (2)Linux系统,可以按照先前的命令apt-get install openssh-server openssh-client安装ssh服务。
        
        在客户端机器我的账号是huixiao200068,在用户家目录中生成ssh-key:
            (1)Windows机器,打开git bash软件,输入命令
                        cd ~
                        ssh-keygen -t rsa
            (2)Linux系统,也执行以上相同的命令,即可以生成当前用户的ssh-key。
            执行完成之后,输入命令:ls -al,如果出现了.ssh目录,则表示ssh-key成功创建。
    2、把ssh的公钥上传到服务器,我这里假设上传到服务器的临时目录/tmp。
        scp  ~/.ssh/id_rsa.pub git@server:/tmp    //命令中的server改成你自己服务器的IP
    到此为止,仅仅只是做好了初始化仓库的准备工作,上面的2步操作都是在客户端操作的。下面是关键的第三步——初始化,该步骤在服务器端执行。
 
    3、初始化
        sudo -H -u git gitosis-init < /tmp/id_rsa.pub    //将git仓库目录初始化到了git用户家目录下
        此时,git用户的home目录中将出现repositories目录,该目录为git的仓库。
        修改目录权限:sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update,该步骤尚不清楚其具体的作用,修改了这个目录的权限有啥用呢?望各位指教。
恭喜你,到此为止,你已经创建了一个git仓库,而且账号huixiao200068是git仓库的管理员啦。下面要做的就是仓库配置啦,管理项目和用户。
四、下载仓库配置项目gitosis-admin到本地客户端
        因为git仓库的配置文件都是以git方式来管理的,所以你需要先下载一份到客户端本地 。
        在你的用户目录下面创建一个临时目录work,
        然后 进入到该目录:cd work,
        然后执行命令:
        git clone git@server:gitosis-admin.git    // 命令中的server改成你自己服务器的IP
        执行完成之后,work目录下会生成gitosis-admin目录,目录下面有一个gitosis.conf文件和一个keydir目录,它们将是下面配置任务的主要操作对象,请牢记它们的位置。
五、新建项目
       1、修改配置文件gitosis.conf,增加如下内容。
            [group first-pro]    //用户组名
            members = huixiao200068    //成员名,多个成员可以用空格隔开
            writable = first-pro    //项目名及其用户对于此项目的权限,目前是可写
        2、创建项目目录 mkdir first-pro
             初始化该目录 cd first-pro;    git init
             添加远程仓库 git remote add origin git@SERVER:first-pro.git
             创建工程文件 touch 1.txt
             添加工程文件到本地仓库中 git add ./1.txt
             提交整个项目到本地仓库 git commit -m “comment”
             提交整个项目到远程仓库 git push origin master    //只有这样子,团队其他开发人员才能看到你修改的代码
             查看提交日志 git log
             查看本地库当前的状态,比如是否有文件需要提交。 git status
        新的项目仓库已经生成,其他开发人员可以git clone 命令从服务器上下载一份工程到自己的本地机器上,协同开发啦!
 
六、新建用户

        关于上一节最后提到的内容,“其他开发人员”,他们是需要管理员来增加和配置的,这一节主要讲怎么添加用户。

(1)客户端操作:
        首先要生成ssh-key,方法和上述说明的一样。
        cd ~
        ssh-keygen -t rsa
        然后一直回车,就OK。然后将生成的id_rsa.pub文件传给GIT服务器管理员
 
(2)服务器端操作:
        管理员将客户上传的id_rsa.pub文件移到gitosis-admin/keydir目录中,并且改名为CLIENT_NAME.pub。注意:如果客户端如下图所示
        ,则CLIENT_NAME为sean@bogon,否则后续操作会出现“Repository read access denied”的错误。
         给项目first-pro增加新的开发者,编辑gitosis.conf文件,vi gitosis.conf。
          [group first-pro]    //用户组名
          members = huixiao200068 sean@bogon    //成员名,多个成员可以用空格隔开
          writable = first-pro    //项目名及其用户对于此项目的权限,目前是可写
         提交修改的管理文件:
            git commit -a -m “add user sean@bogon”
            git push origin master
完成上述2步之后,即可以使用该账号共同开发项目first-pro啦!
        cd ~
        git clone git@SERVER:first-pro.git    //克隆项目到本地
        ……    //do anything you want to do
        commit -am “comment”
        commit push origin master
link: http://blog.163.com/xiaohui_1123@126/blog/static/398052402012102751349705/

在默认拥有的腾讯云服务器是没有额外的数据盘的,默认Linux只有8GB系统盘,一般的网站也足够使用,如果额外购买的数据盘安装系统之后根据不同的面板、系统的路径问题可能不会自动加载到指定的数据盘目录,需要我们手工进行加载数据盘 ,也就是我们常说的挂载。

第一、检查硬盘设备是否有数据盘

当然,在写这篇文章的时候,我是知道有数据盘的,但有些时候我们购买的VPS,默认比如30GB,可能还有20GB没有挂载,所以也需要类似这样的操作先检查一遍。

fdisk -l

检查腾讯云服务器数据硬盘

我们可以看到有268GB的数据盘没有挂载,看好前面的路径/dev/vdb

第二、数据硬盘分区

fdisk /dev/vdb

依次输入 n 、p、 1、 回车、回车、wq

这里的VDB是我们上面看到数据硬盘的名称,如果你不是这个需要根据你真实的盘名称替换,如果是和我一样,那就直接复制。

第三、ext3格式化分区

mkfs.ext3 /dev/vdb1

第四、挂载新分区

A – 新建目录

mkdir /home

因为AMH面板是安装在HOME目录的,所以我们需要新建目录,如果是WDCP面板,我们应该知道是WWW目录。

B – 挂载分区

mount /dev/vdb1 /home

第五、写入fstab 设置开机自动挂载

echo ‘/dev/vdb1 /home ext3 defaults 0 0’ >> /etc/fstab

第六、检查是否挂载成功(df -h )

这里我们可以看到247GB(250GB)已经挂载完成,在HOME目录中。

 

link: http://www.laozuo.org/4888.html

Linux默认情况下使用UTC格式作为标准时间格式,如果在Linux下运行程序,且在程 序中指定了与系统不一样的时区的时候,可能会造成时间错误。如果是Ubuntu的桌面版,则可以直接在图形模式下修改时区信息,但如果是在Server版 呢,则需要通过tzconfig来修改时区信息了。使用方式(如将时区设置成Asia/Chongqing):

 

sudo tzconfig,如果命令不存在请使用 dpkg-reconfigure tzdata

然后按照提示选择 Asia对应的序号,选完后会显示一堆新的提示—输入城市名,如Shanghai或Chongqing,最后再用 sudo date -s “” 来修改本地时间。

按照提示进行选择时区,然后:

sudo cp /usr/share/zoneinfo/Asia/ShangHai /etc/localtime

上面的命令是防止系统重启后时区改变。

 

网上同步时间

1.  安装ntpdate工具

# sudo apt-get install ntpdate

2.  设置系统时间与网络时间同步

# ntpdate cn.pool.ntp.org

3.  将系统时间写入硬件时间

# hwclock –systohc

cn.pool.ntp.org是位于中国的公共NTP服务器,用来同步你的时间(如果你的时间与服务器的时间截不同的话,可能无法同步时间哟,甚至连sudo reboot这样的指令也无法执行)。

 

link: http://www.cnblogs.com/php5/archive/2011/02/15/1955432.html

Valgrind简介:

Valgrind是动态分析工具的框架。有很多Valgrind工具可以自动的检测许多内存管理和多进程/线程的bugs,在细节上剖析你的程序。你也可以利用Valgrind框架来实现自己的工具。

Valgrind通常包括6个工具:一个内存错误侦测工具,两个线程错误侦测工具,cache和分支预测的分析工具,堆的分析工具。

Valgrind的使用与CPU OS以及编译器和C库都有关系。目前支持下面的平台:

– x86/Linux

– AMD64/Linux

– PPC32/Linux

– PPC64/Linux

– ARM/Linux

– x86/MacOSX

– AMD64/MacOSX

 

Valgrind是GNU v2下的开源软件,你可以从http://valgrind.org下载最新的源代码。

 

Valgrind的安装:

1.从http://valgrind.org下载最新的valgrind-3.7.0.tar.bz2d,用tar -xfvalgrind-3.7.0.tar.bz2解压安装包。

2.执行./configure,检查安装要求的配置。

3.执行make。

4.执行make install,最好是用root权限。

5.试着valgrind ls -l来检测是否正常工作。

 

 

Valgrind的概述:

Valgrind时建立动态分析工具的框架。它有一系列用于调试分析的工具。Valgrind的架构是组件化的,所以可以方便的添加新的工具而不影响当前的结构。

 

下面的工具是安装时的标准配置:

Memcheck:用于检测内存错误。它帮助c和c++的程序更正确。

Cachegrind:用于分析cache和分支预测。它帮助程序执行得更快。

Callgrind:用于函数调用的分析。

Helgrind:用于分析多线程。

DRD:也用于分析多线程。与Helgrind类似,但是用不同的分析技术,所以可以检测不同的问题。

Massif:用于分析堆。它帮助程序精简内存的使用。

SGcheck:检测栈和全局数组溢出的实验性工具,它和Memcheck互补使用。

 

 

Valgrind的使用:

1.准备好程序:

编译程序时用-g,这样编译后的文件包含调试信息,那Memcheck的分析信息中就包含正确的行号。最好使用-O0的优化等级,使用-O2及以上的优化等级使用时可能会有问题。

2.在Memcheck下运行程序:

如果你的程序执行如下:

myprog arg1 arg2

那么使用如下:

valgrind –leak-check=yes myprog arg1 arg2

Memcheck是默认的工具。–leak-check打开内存泄漏检测的细节。

在上面的命令中运行程序会使得程序运行很慢,而且占用大量的内存。Memcheck会显示内存错误和检测到的内存泄漏。

3.如何查看Memcheck的输出:

这里有一个实例c代码(a.c),有一个内存错误和一个内存泄漏。

#include <stdlib.h>

void f(void)

{

int*x = (int *)malloc(10 * sizeof(int));

x[10]= 0;

//problem 1: heap block overrun

}        //problem 2: memory leak — x not freed

 

int main(void)

{

f();

return0;

}

 

运行如下:

huerjia@huerjia:~/NFS/valg/test$ valgrind–leak-check=yes ./a

==24780== Memcheck, a memory error detector

==24780== Copyright (C) 2002-2011, and GNUGPL’d, by Julian Seward et al.

==24780== Using Valgrind-3.7.0 and LibVEX;rerun with -h for copyright info

==24780== Command: ./a

==24780==

==24780== Invalid write of size 4

==24780==   at 0x80484DF: f() (a.c:5)

==24780==   by 0x80484F1: main (a.c:11)

==24780== Address 0x42d3050 is 0 bytes after a block of size 40 alloc’d

==24780==   at 0x4026444: malloc (vg_replace_malloc.c:263)

==24780==   by 0x80484D5: f() (a.c:4)

==24780==   by 0x80484F1: main (a.c:11)

==24780==

==24780==

==24780== HEAP SUMMARY:

==24780==     in use at exit: 40 bytes in 1 blocks

==24780==  total heap usage: 1 allocs, 0 frees, 40 bytes allocated

==24780==

==24780== 40 bytes in 1 blocks aredefinitely lost in loss record 1 of 1

==24780==   at 0x4026444: malloc (vg_replace_malloc.c:263)

==24780==   by 0x80484D5: f() (a.c:4)

==24780==   by 0x80484F1: main (a.c:11)

==24780==

==24780== LEAK SUMMARY:

==24780==   definitely lost: 40 bytes in 1 blocks

==24780==   indirectly lost: 0 bytes in 0 blocks

==24780==      possibly lost: 0 bytes in 0 blocks

==24780==   still reachable: 0 bytes in 0 blocks

==24780==         suppressed: 0 bytes in 0 blocks

==24780==

==24780== For counts of detected andsuppressed errors, rerun with: -v

==24780== ERROR SUMMARY: 2 errors from 2contexts (suppressed: 17 from 6)

 

如何来阅读这个输出结果:

==24780== Memcheck, a memory error detector

==24780== Copyright (C) 2002-2011, and GNUGPL’d, by Julian Seward et al.

==24780== Using Valgrind-3.7.0 and LibVEX;rerun with -h for copyright info

==24780== Command: ./a

这一部分是显示使用的工具以及版本信息。其中24780是Process ID。

 

==24780== Invalid write of size 4

==24780==   at 0x80484DF: f() (a.c:5)

==24780==   by 0x80484F1: main (a.c:11)

==24780== Address 0x42d3050 is 0 bytes after a block of size 40 alloc’d

==24780==   at 0x4026444: malloc (vg_replace_malloc.c:263)

==24780==   by 0x80484D5: f() (a.c:4)

==24780==   by 0x80484F1: main (a.c:11)

这部分指出了错误:Invalid write。后面的几行显示了函数堆栈。

 

==24780== HEAP SUMMARY:

==24780==     in use at exit: 40 bytes in 1 blocks

==24780==  total heap usage: 1 allocs, 0 frees, 40 bytes allocated

==24780==

==24780== 40 bytes in 1 blocks aredefinitely lost in loss record 1 of 1

==24780==   at 0x4026444: malloc (vg_replace_malloc.c:263)

==24780==   by 0x80484D5: f() (a.c:4)

==24780==   by 0x80484F1: main (a.c:11)

==24780==

==24780== LEAK SUMMARY:

==24780==   definitely lost: 40 bytes in 1 blocks

==24780==   indirectly lost: 0 bytes in 0 blocks

==24780==      possibly lost: 0 bytes in 0 blocks

==24780==   still reachable: 0 bytes in 0 blocks

==24780==         suppressed: 0 bytes in 0 blocks

这部分是对堆和泄漏的总结,可以看出内存泄漏的错误。

 

==24780== For counts of detected andsuppressed errors, rerun with: -v

==24780== ERROR SUMMARY: 2 errors from 2contexts (suppressed: 17 from 6)

这部分是堆所有检测到的错误的总结。代码中的两个错误都检测到了。

 

 

 

Helgrind:线程错误检测工具

若使用这个工具,在Valgrind的命令中添加–tool=helgrind。

Helgrind用于c,c++下使用POSIXpthreads的程序的线程同步错误。

Helgrind可以检测下面三类错误:

1.POSIX pthreads API的错误使用

2.由加锁和解锁顺序引起的潜在的死锁

3.数据竞态–在没有锁或者同步机制下访问内存

 

以数据竞态为例来说明Helgrind的用法:

在不使用合适的锁或者其他同步机制来保证单线程访问时,两个或者多个线程访问同一块内存就可能引发数据竞态。

一个简单的数据竞态的例子:

#include <pthread.h>

 

int var = 0;

 

void* child_fn ( void* arg ) {

var++;/* Unprotected relative to parent */ /* this is line 6 */

returnNULL;

}

 

int main ( void ) {

pthread_tchild;

pthread_create(&child,NULL, child_fn, NULL);

var++;/* Unprotected relative to child */ /* this is line 13 */

pthread_join(child,NULL);

return0;

}

 

运行如下:

huerjia@huerjia:~/NFS/valg/test$ valgrind–tool=helgrind ./b

==25449== Helgrind, a thread error detector

==25449== Copyright (C) 2007-2011, and GNUGPL’d, by OpenWorks LLP et al.

==25449== Using Valgrind-3.7.0 and LibVEX;rerun with -h for copyright info

==25449== Command: ./b

==25449==

==25449==—Thread-Announcement——————————————

==25449==

==25449== Thread #1 is the program’s rootthread

==25449==

==25449== —Thread-Announcement——————————————

==25449==

==25449== Thread #2 was created

==25449==   at 0x4123A38: clone (in /lib/tls/i686/cmov/libc-2.11.1.so)

==25449==   by 0x40430EA: pthread_create@@GLIBC_2.1 (in /lib/tls/i686/cmov/libpthread-2.11.1.so)

==25449==   by 0x402A9AD: pthread_create_WRK (hg_intercepts.c:255)

==25449==   by 0x402AA85: pthread_create@* (hg_intercepts.c:286)

==25449==   by 0x80484E1: main (b.c:11)

==25449==

==25449==—————————————————————-

==25449==

==25449== Possible data race during read ofsize 4 at 0x804A020 by thread #1

==25449== Locks held: none

==25449==   at 0x80484E2: main (b.c:12)

==25449==

==25449== This conflicts with a previouswrite of size 4 by thread #2

==25449== Locks held: none

==25449==   at 0x80484A7: child_fn (b.c:6)

==25449==   by 0x402AB04: mythread_wrapper (hg_intercepts.c:219)

==25449==   by 0x404296D: start_thread (in /lib/tls/i686/cmov/libpthread-2.11.1.so)

==25449==   by 0x4123A4D: clone (in /lib/tls/i686/cmov/libc-2.11.1.so)

==25449==

==25449==—————————————————————-

==25449==

==25449== Possible data race during writeof size 4 at 0x804A020 by thread #1

==25449== Locks held: none

==25449==   at 0x80484E2: main (b.c:12)

==25449==

==25449== This conflicts with a previouswrite of size 4 by thread #2

==25449== Locks held: none

==25449==   at 0x80484A7: child_fn (b.c:6)

==25449==   by 0x402AB04: mythread_wrapper (hg_intercepts.c:219)

==25449==   by 0x404296D: start_thread (in /lib/tls/i686/cmov/libpthread-2.11.1.so)

==25449==   by 0x4123A4D: clone (in /lib/tls/i686/cmov/libc-2.11.1.so)

==25449==

==25449==

==25449== For counts of detected andsuppressed errors, rerun with: -v

==25449== Use –history-level=approx or=none to gain increased speed, at

==25449== the cost of reduced accuracy ofconflicting-access information

==25449== ERROR SUMMARY: 2 errors from 2contexts (suppressed: 0 from 0)

 

错误信息从“Possible data race during write of size 4 at 0x804A020 by thread #1

”开始,这条信息你可以看到竞态访问的地址和大小,还有调用的堆栈信息。

第二条调用堆栈从“This conflicts with a previous write of size 4 by thread #2

”开始,这表明这里与第一个调用堆栈有竞态。

 

一旦你找到两个调用堆栈,如何找到竞态的根源:

首先通过每个调用堆栈检查代码,它们都会显示对同一个位置或者变量的访问。

现在考虑如何改正来使得多线程访问安全:

1.使用锁或者其他的同步机制,保证同一时间只有独立的访问。

2.使用条件变量等方法,确定多次访问的次序。

 

 

本文介绍了valgrind的体系结构,并重点介绍了其应用最广泛的工具:memcheck和helgrind。阐述了memcheck和helgrind的基本使用方法。在项目中尽早的发现内存问题和多进程同步问题,能够极大地提高开发效率,valgrind就是能够帮助你实现这一目标的出色工具。

 

link: http://blog.csdn.net/dndxhej/article/details/7855520

当连接数多时,经常出现大量FIN_WAIT1,可以修改 /etc/sysctl.conf
修改

net.ipv4.tcp_fin_timeout = 10
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_sack = 0

然后:

/sbin/sysctl -p

使之生效
#######################################################################################
apache服务器的time_wait过多 fin_wait1过多等问题
1。time_wait状态过多。
    通常表现为apache服务器负载高,w命令显示load average可能上百,但是web服务基本没有问题。同时ssh能够登陆,但是反应非常迟钝。
原因:最可能的原因是httpd.conf里面keepalive没有开,导致每次请求都要建立新的tcp连接,请求完成以后关闭,增加了很多 time_wait的状态。另,keepalive可能会增加一部分内存的开销,但是问题不大。也有一些文章讨论到了sysctl里面一些参数的设置可以改善这个问题,但是这就舍本逐末了。
2。fin_wait1状态过多。fin_wait1状态是在server端主动要求关闭tcp连接,并且主动发送fin以后,等待client端回复ack时候的状态。fin_wait1的产生原因有很多,需要结合netstat的状态来分析。
netstat -nat|awk ‘{print awk $NF}’|sort|uniq -c|sort -n
上面的命令可以帮助分析哪种tcp状态数量异常
netstat -nat|grep “:80″|awk ‘{print $5}’ |awk -F: ‘{print $1}’ | sort| uniq -c|sort -n
则可以帮助你将请求80服务的client ip按照连接数排序。
回到fin_wait1这个话题,如果发现fin_wait1状态很多,并且client ip分布正常,那可能是有人用肉鸡进行ddos攻击、又或者最近的程序改动引起了问题。一般说来后者可能性更大,应该主动联系程序员解决。
但是如果有某个ip连接数非常多,就值得注意了,可以考虑用iptables直接封了他。

因为我们的svn服务器的版本太低(1.4.2版本),而我们需要用到1.6以上版本的目录合并功能,因此,需要对我们的svn服务器进行了升级。按照以前的安装方法进行了安装,发现出了不少问题。

原因是以前安装的时候操作系统是32位的系统,此次安装的为64位的系统。

再次记录上此次成功安装的步骤:

  1. 下载、编译和安装openssl [可选]

如果想让svn服务器支持https等加密的ssl链接,需要编译此模块

[flavorzhu@self ~]$ wget http://www.openssl.org/source/openssl-1.0.0d.tar.gz

[flavorzhu@self ~]$tar -zxvf openssl-1.0.0d.tar.gz

[flavorzhu@self ~]$cd openssl-1.0.0d

[flavorzhu@self ~]$./config –prefix=/usr/local/openssl

[flavorzhu@self ~]$sudo make  && make install

  1. 下载、编译和安装apache

[flavorzhu@self ~]$wget http://mirror.bjtu.edu.cn/apache/httpd/httpd-2.2.19.tar.gz

[flavorzhu@self ~]$tar  -zxvf  httpd-2.2.19.tar.gz

[flavorzhu@self ~]$cd httpd-2.2.19

[flavorzhu@self ~]$./configure –prefix=/usr/local/apache \

–enable-lib64 \

–enable-mods-shared=all

[flavorzhu@self ~]$ sudo make && make install

  1. 下载、编译和安装BerkeleyDB

http://www.oracle.com/technetwork/database/berkeleydb/downloads/index.html 下载Berkeley db,编译并安装

比如我下载的是4.8.24版本

[flavorzhu@self ~]$tar -zxvf db-4.8.24.tar.gz

[flavorzhu@self ~]$cd db-4.8.24/build_unix/

[flavorzhu@self ~]$../dist/configure –/usr/local/BerkeleyDB.4.8

[flavorzhu@self ~]$sudo make && make install

将Berkeley DB的.so加入到ld.so.conf中

[flavorzhu@self ~]$sudo  echo /usr/local/BerkeleyDB.4.8 >> /etc/ld.so.conf

[flavorzhu@self ~]$sudo /sbin/ldconfig

svn的存储有Berkeley DB(2001年开始支持) 和 FSFS(2004年开始支持)系统两种存储,默认使用的是FSFS模式的(如果没有安装Berkeley DB)。

详情见:http://www.zhuyanbin.com/?p=74

  1. 下载、编译和安装subversion依赖包

[flavorzhu@self ~]$wget  http://subversion.tigris.org/downloads/subversion-deps-1.6.16.tar.gz

[flavorzhu@self ~]$tar zxvf subversion-deps-1.6.16.tar.gz

[flavorzhu@self ~]$cd subversion-1.6.16

4.1 安装apr

注:Apache Portable Runtime

[flavorzhu@self ~]$cd apr

[flavorzhu@self ~]$./configure –prefix=/usr/local/apache LDFLAGS=”-L/lib6″

[flavorzhu@self ~]$sudo make && make install

4.2 编译和安装apr-util

[flavorzhu@self ~]$cd apr-util

[flavorzhu@self ~]$./configure –prefix=/usr/local/apache –with-apr=/usr/local/apache LDFLAGS=”-L/lib64″ –with-berkeley-db=/usr/local/BerkeleyDB.4.8

[flavorzhu@self ~]$sudo make && make install

4.3 编译和安装neon

注:neon是使得svn客户端支持http和https协议的关键模块

[flavorzhu@self ~]$cd neon/

[flavorzhu@self ~]$./configure –prefix=/usr/local/neon –enable-shared –enable-ssl –with-ssl=openssl LDFLAGS=”-L/lib64″

[flavorzhu@self ~]$sudo make && make install

4.4 编译和安装serf

[flavorzhu@self ~]$cd serf/

[flavorzhu@self ~]$./configure –prefix=/usr/local/serf –with-apr=/usr/local/apache –with-apr-util=/usr/local/apache –with-openssl=/usr/local/openssl LDFLAGS=”-L/lib64″

[flavorzhu@self ~]$sudo make && make install

4.5 编译和安装zlib

[flavorzhu@self ~]$cd zlib/

[flavorzhu@self ~]$./configure –prefix=/usr/local/zlib

[flavorzhu@self ~]$sudo make && make install

4.6 下载、编译和安装subversion

[flavorzhu@self ~]$wget  http://subversion.tigris.org/downloads/subversion-1.6.16.tar.gz

[flavorzhu@self ~]$tar zxvf subversion-1.6.16.tar.gz

[flavorzhu@self ~]$ cd subversion-1.6.16

将subversion依赖包中的sqlite-amalgamation拷贝到subversion-1.6.16里

[flavorzhu@self ~]$./autogen.sh

[flavorzhu@self ~]$./configure  –with-ssl –with-zlib=/usr/local/zlib –with-apr=/usr/local/apache –with-apr-util=/usr/local/apache –with-serf=/usr/local/serf –with-neon=/usr/local/neon LDFLAGS=”-L/lib64″

[flavorzhu@self ~]$sudo make && make install

注:在make之前检查一下,subversion里的Makefile的BerkeleyDB的lib包使用引用正确的版本,具体搜索一下, 比如我的是“-ldb-4.8”

配置apache

修改httpd.conf,增加如下代码

LoadModule dav_module modules/mod_dav.so

LoadModule dav_svn_module     modules/mod_dav_svn.so

LoadModule authz_svn_module   modules/mod_authz_svn.so

<Location /svn>

DAV svn

SVNParentPath /absolute/path/to/repository

AuthzSVNAccessFile /my/svn/user/authz.conf

AuthType Basic

AuthName “Subversion”

AuthUserFile  /my/svn/user/passwd/file

Require valid-user

</Location>

 

  1. subversion仓库的升级

5.1 方法一 upgrade方式

svnadmin upgrade /path/to/repository

5.2 方法二 dump/load方式

svnadmin dump your-repository > repository.dump

svnadmin create your-repository

svnadmin load your-repository < repository.dump

经过测试,使用dump/load方式比较靠谱,不管你使用那种方式升级你的仓库,操作之前备份你的仓库都是不可省略的步骤。