Pages:  1 2 Server – lytsing's Blog

Category: Server

  • Gitlab 日常维护

    安装完gitlab只是第一步,后期维护还需要费力。

    文件约定

    VERSION 文件

    每个项目要增加这个文件,里面写着版本号, 效果见 https://gitlab.com/gitlab-org/gitlab-ce 右则导航栏,方便查看当前版本号。

    .gitignore

    避免提交一堆垃圾文件,及时加上.gitignore文件,有在线工具生成 https://www.gitignore.io/

    版本升级

    参考官方提供的文档 https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md 操作,一般不会遇到遇到很大的问题。如果本地修改一些文件,自动升级的脚本会执行git stash存档,同步完后,需要手动 git stash pop

    但不会是一劳永逸,lib 目录下一些配置更新了,还需要对照版本升级说明 https://github.com/gitlabhq/gitlabhq/tree/master/doc/update 手动修改 。

    以上的方式,比较适合不需要对gitlab大修改,如果定制自己的UI或页面,最好建立自己的分支:

    su - git
    cd /home/git/gitlab/
    git checkout -b my_branch
    1. Stop gitlab service
    2. Run git fetch –all
    3. Run git branch 7-5-stable origin/7-5-stable (replace with appropriate version)
    4. Run git rebase 7-5-stable my_branch
    5. Follow the rest of instructions (db:migrate, assets:precompile, etc.)

    参考: http://axilleas.me/en/blog/2014/custom-gitlab-login-page/

    代码备份

    已经有人写了一个脚本脚本,见 https://github.com/sund/auto-gitlab-backup 定期把备份数据拷贝到备机,避免硬盘挂掉的悲剧,更保险一点,需要每月拷贝到移动硬盘上存档。

    性能优化

    Nginx

    根据CPU,work数跟CPU数一样。

  • CentOs 6.5 安装 GitLab 笔记

    硬件要求: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/install/requirements.md
    注意了,使用阿里云最便宜的主机,内存只有1G,会不够的哦,需要使用 swap交换分区,具体操作自行Google。

    虽然可以按照官方文档 https://github.com/gitlabhq/gitlab-recipes/tree/master/install/centos 从头到尾 ctrl+c、ctrl+v,但有些地方需要注意的。

    使用Ruby镜像

    在运行

    gem install bundler --no-doc

    之前,参考这个 http://ruby.taobao.org/ ,使用淘宝提供的镜像,感谢阿里。否则要等半天。

    nginx启动问题

    [root@git gitlab-shell]# service nginx restart
    Stopping nginx: [FAILED]
    Starting nginx: nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:443 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:443 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:443 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:443 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:80 failed (98: Address already in use)
    nginx: [emerg] bind() to [::]:443 failed (98: Address already in use)

    编辑 /etc/nginx/conf.d/gitlab.conf,将ipv6端口注释掉,我们还没有高级的使用ipv6。
    listen 0.0.0.0:80;
    # listen [::]:80 default_server;

    listen 0.0.0.0:443 ssl;
    #listen [::]:443 ssl default_server;

    nginx再启动,运行正常,打开网页报 500错误,查看 log发现:

    == Seed from /home/git/gitlab/db/fixtures/production/001_admin.rb
    2014-11-08T15:52:20Z 25461 TID-otwilgzbo INFO: Sidekiq client with redis options {:url=>”unix:/var/run/redis/redis.sock”, :namespace=>”resque:gitlab”}
    rake aborted!

    Errno::EACCES: Permission denied – connect(2) for /var/run/redis/redis.sock

    简单粗暴的方式,把权限都打开了,

    # chmod 777 /var/run/redis/redis.sock

    不过每次都要设置,终极方案是要再补一刀。
    # echo -e 'unixsocketperm 775' | sudo tee -a /etc/redis.conf

    邮件发送问题

    默认安装postfix,死活没有发送出去,查看日志cat /var/log/maillog,才知道要配置一下 主机,域名,编辑 /etc/postfix/main.cf,把myhostname,mydomain这两个值取消注释,填上你的值。

    myhostname = git.XXX.com
    #myhostname = virtual.domain.tld

    # The mydomain parameter specifies the local internet domain name.
    # The default is to use $myhostname minus the first component.
    # $mydomain is used as a default value for many other configuration
    # parameters.
    #
    mydomain = XXX.com

    如果是阿里云主机需要打开这个:
    #myorigin = $myhostname
    myorigin = $mydomain

    然后重启。测试邮件是否可以发出去,简单的方式是使用mail 命令行发送:

    mail -s "hello world” your_email

    回车,随便输入几个字,ctrl +d 结束输入。

    修改logo

    在 /home/git/gitlab/app/assets 这目录下,

    images/brand_logo.png
    images/favicon.ico
    images/logo-black.png
    images/logo-white.png

    把这几个图片改成你自己的,再重新编译资源文件:

    sudo -u git RAILS_ENV=production bundle exec rake assets:precompile

    重启 gitlab。

    修改默认皮肤

    编译 config/gitlab.yml
    # default_theme: 2 # default: 2

    注释取消,记得要与上面的这一行 default_projects_limit: 10 对齐,多个空格少个空格都不行,不然启动报错,rails新手会经常犯错。当然,每个开发成员可以定制主题,Profile Settings -> Design,爱哪选哪。

    其他注意

    默认master分支是受保护的,developer成员没有权限提交,所以,要开发成员组自己创建分支,管理员才有权限 merge进来。

    btw:) windows用户使用可能比较蛋疼,他们不太喜欢在命令行敲,需要有个学习适应的过程。

    Puma 替换 Unicorn

    为性能考虑,使用Puma,不过要跟jruby使用,不然会遇到多线程并发问题。参考 这篇 http://icyleaf.com/2014/01/moving-unicorn-to-puma-on-gitlab/

    运行的时候,遇到:
    [root@git gitlab]# service gitlab start
    /etc/init.d/gitlab: line 38: PPID: readonly variable
    Starting puma: /etc/init.d/gitlab: Usage: daemon [+/-nicelevel] {program}

    ^[[Ating sidekiq: [ OK ]

    PPID跟系统的冲突了,改成 UPID即可。已经提交补丁,https://gitlab.com/lytsing/gitlab-recipes/commit/3c8d0a35f54f93caac28bac464829dba7e6dc736

  • 试用 zimg服务器

    同事推荐这个库做图片服务器,一看作者是88年的,好小,在百度工作过,稍微看了一下,照着 zimg服务器搭建手记 安装,还是遇到一些麻烦,我使用的系统是 CentOS release 6.2,64bit。

    安装依赖包 libmemcached,ImageMagick,openssl, libevent:
    yum install gcc-c++ gcc automake git libmemcached-devel ImageMagick-devel openssl-devel libevent-devel

    安装 cmake

    如果使用 yum install cmake 安装,版本太低,编译libevhtp-1.2.6 会报错:
    # cmake -DCMAKE_PREFIX_PATH=/usr -DCMAKE_INSTALL_PREFIX=/usr/
    CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
    CMake 2.8 or higher is required. You are running version 2.6.4

    需要手动下载安装

    wget http://www.cmake.org/files/v2.8/cmake-2.8.10.2.tar.gz
    tar xvf cmake-2.8.10.2.tar.gz
    cd cmake-2.8.10.2
    ./bootstrap --prefix=/usr && make && make install

    wget https://github.com/ellzey/libevhtp/archive/1.2.6.tar.gz -O libevhtp-1.2.6.tar.gz
    tar xvf libevhtp-1.2.6.tar.gz
    cd libevhtp-1.2.6
    cmake -DCMAKE_PREFIX_PATH=/usr -DCMAKE_INSTALL_PREFIX=/usr -DLIBEVENT_PTHREADS_LIBRARY=/usr/lib -DLIBEVENT_OPENSSL_LIBRARY=/usr/lib64/openssl/
    make && make install

    wget https://github.com/buaazp/zimg/archive/master.zip
    unzip zimg-master.zip
    cd zimg-master
    make

    报错:

    cc -Wall -c -o zimg.o zimg.c
    zimg.c:27:29: error: wand/MagickWand.h: No such file or directory

    这个 Makefile 写的确实不是很专业,需要手动修改才可以编译通过,至少起码应该使用 automake或cmake。手动添加 MagickWand 头文件路径。然后链接的时候又报错:

    zhttpd.o: In function `guess_type’:
    zhttpd.c:(.text+0x28): undefined reference to `evutil_ascii_strcasecmp’
    zhttpd.o: In function `guess_content_type’:
    zhttpd.c:(.text+0xb8): undefined reference to `evutil_ascii_strcasecmp’

    需要指定 -L/usr/lib 才行,下面是给Makefile打的补丁:

    [root@dmzsrv01 zimg]# git diff Makefile
    diff --git a/Makefile b/Makefile
    index 315a8c4..05295b1 100644
    --- a/Makefile
    +++ b/Makefile
    @@ -4,10 +4,10 @@ MAC = Darwin
    ifeq ($(OS),Darwin)
    LIBS = -levent -levent_openssl -levent_pthreads -lssl -lcrypto -levhtp -lMagickWand-6.Q16 -lmemcached
    else
    - LIBS = -levent -levent_openssl -levent_pthreads -lssl -lcrypto -levhtp -lMagickWand -lmemcached
    + LIBS = -L /usr/lib -levent -levent_openssl -levent_pthreads -lssl -lcrypto -levhtp -lMagickWand -lmemcached
    endif
    OBJS = zhttpd.o zspinlock.o zlog.o zmd5.o zutil.o zcache.o zimg.o main.o
    -CFLAGS = -Wall
    +CFLAGS = -Wall -g -I /usr/include/ImageMagick -DMAGICKCORE_HDRI_ENABLE=0 -DMAGICKCORE_QUANTUM_DEPTH=16
    all: ${OBJS}
    gcc ${CFLAGS} -o zimg ${OBJS} ${LIBS}

    使用还是比较简单的,help 就可以了。需要注意的是,这个 zimg 不能运行两次,会 core dump,程序本身没处理好。最后,fork 这个项目,花了一会时间写 CMakeLists.txt 使用cmake编译,已经 pull request给作者。现在安装更方便了,在 Ubuntu 13.10 Server 测试通过:

    sudo apt-get  install cmake libssl-dev libevent-dev libmagickwand-dev libmemcached-dev
    
    wget https://github.com/ellzey/libevhtp/archive/1.2.6.tar.gz
    tar xvf libevhtp-1.2.6.tar.gz
    cd libevhtp-1.2.6/
    cmake .
    make
    sudo make install
    
    cd ..
    git clone https://github.com/lytsing/zimg
    cd zimg/
    cmake .

    跑了 test目录下的测试脚本,发现性能还是挺不错的,目前这个版本还不支持访问认证以及https,支持https需要手动写,参考 libevhtp 提供的example添加不是难事。至于生产与访问文件的 url名称 是文件的 md5 值,可以在这基础上稍微做个变化,显得更专业一些。文件存储与MooseFS 结合倒是不错的选择。

  • 当心avahi-daemon

    我们的系统时不时报

    java.net.ConnectException: Connection timed out
            at java.net.PlainSocketImpl.socketConnect(Native Method)
            at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
            at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
            at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
            at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:366)
            at java.net.Socket.connect(Socket.java:529)
            at java.net.Socket.connect(Socket.java:478)
            at java.net.Socket.<init>(Socket.java:375)
            at java.net.Socket.<init>(Socket.java:189)

    这样的错误日志。被连接的server 系统负载不是很高,资源也足够,一时找不到原因。分析日志出现的时间:

    $ grep “router socket IO Exception” router.log |awk ‘{print $2}’|sort -u
    10:15:05,155
    10:15:13,467
    12:15:06,129
    12:15:13,419
    13:15:06,012
    13:15:06,148
    13:15:07,168
    13:15:08,812
    13:15:11,781
    13:15:14,154
    13:15:14,510
    15:15:05,306
    15:15:05,639
    16:15:06,709
    16:15:07,083
    16:15:07,447
    16:15:07,850
    16:15:07,915
    16:15:08,888
    16:15:10,359
    16:15:12,553
    16:15:14,246
    17:15:08,219
    17:15:08,239
    17:15:09,055
    17:15:12,094
    18:15:06,008
    18:15:08,460
    18:15:10,428
    18:15:12,057
    18:15:12,692
    19:15:11,374
    19:15:12,061
    19:15:12,089
    19:15:13,746
    21:15:08,496
    21:15:11,356
    21:15:12,393
    21:15:13,462
    21:15:14,495

    都出现在神秘的15分钟,应该是定时jobs在跑导致的。检查crontab以及jboss的jobs任务,也找不到。最后只能tcpdump在14-16分抓包分析。得知 server 启用了avahi-daemon服务,每隔一个小时发送一个MDNS的广播包,会造成 server 无回应20秒左右。

    avahi-daemon 是什么? 来自 http://packages.debian.org/zh-cn/wheezy/avahi-daemon 的解释: Avahi 是一个完全基于 LGPL 框架下的多播 DNS 服务搜寻工具。它能让程序发布或者 发现在本地网络中的服务或者主机,而无需特殊配置。例如,您可以连入一个网络,然后 立刻发现可用于打印的打印机,可查看的文件或者可聊天的朋友。本软件包包含 Avahi 守护进程,它将在网络中展示您的机器,并允许其他应用程序发 布和分析 mDNS/DNS-SD 记录.

    服务器上最好把 avahi-daemon 关闭掉。

  • Android、iOS http请求加上User-agent

    最近在排查一些问题,发现很难下手,nginx 的log如下:

    182.37.109.153 - - [25/Aug/2013:00:02:52 +0800] "-" 400 0 "-" "-" "-"
    182.37.109.153 - - [25/Aug/2013:00:02:52 +0800] "-" 400 0 "-" "-" "-"
    182.37.109.153 - - [25/Aug/2013:00:02:52 +0800] "-" 400 0 "-" "-" "-"
    171.36.8.66 - - [25/Aug/2013:09:40:07 +0800] "POST /xxxxx.htm HTTP/1.1" 200 251 "-" "-" "-"

    不知道哪个请求是Android,哪个是iOS的。Square的Jack在演讲中提到过,他们最开始做后台系统,基于twitter有过的经验,第一个系统不是实现后台交易功能,而是控制台,先做好监控用户的每个交易行为,使得可控。

    iOS 如果使用 ASIHTTPRequest 库,ASIHTTPRequest.m 里的代码如下:

    [self setDefaultUserAgentString:[NSString stringWithFormat:@”%@ %@ (%@; %@ %@; %@)”, appName, appVersion, deviceName, OSName, OSVersion, locale]];
    得到默认的 User-agent: “miniCashbox 2.0.6 (iPhone; iPhone OS 6.1.3; zh_CN)”

    Android可以使用系统提供的,需要设置
    HttpProtocolParams.setUserAgent(params, System.getProperty(“http.agent”));
    结果为:User-agent: “Dalvik/1.6.0 (Linux; U; Android 4.1.2; Nexus S Build/JZO54K)”

    根据实际需要,以上的 User-agent 还不足够满足需要,比如想要知道是哪个用户发送的请求,但不可能把用户id显示出来,那么就需要显示设备的唯一标识 Device Id。系统设计时,用户与终端设备信息的关系是: user has_many devices。从常用的QQ、微信在移动终端登录体验过程中,我们可以感受到的。给客户端做消息push推送,更需要如此做。

    参考: http://cdrussell.blogspot.com/2012/09/programmatically-get-user-agent-string.html