Category Archives: 服务器

解决因jbd2导致mysql性能过低问题

在几个月前,有同事因为需要对某项功能进行压力测试,测试mysql的读写性能。当时测下来的结果非常不满意,本地测试环境性能巨差无比,当时我帮忙找问题,top看cpu、内存完全没有问题,iotop看到有jbd2 I/O占用到了99%。压力测试一结束,也随之降下来。当时排查了一段时间,始终没有搞定,就放弃了。就在这周,还是需要测试mysql性能,还是因为这个问题,我就花了一个下午的时间,终于解决了。

首先我们应该了解一下jbd2是什么东西。为什么I/O会如此之高。随便google一下,都有问到jbd2如何关闭。但是没有一个答案是能搞定的。wikipedia下是这样定义的(JBD):

The Journaling Block Device (JBD) provides a filesystem-independent interface for filesystem journaling. ext3, ext4 and OCFS2 are known to use JBD. OCFS2 starting from linux 2.6.28 and ext4 use a fork of JBD called JBD2

那如何关闭JBD2呢?

首先用 dumpe2fs /dev/sda6 | more 查看Filesystem Feature下有木有has_journal。如果没有就不用看了 -_-

tune2fs -o journal_data_writeback /dev/sda6
tune2fs -O "^has_journal" /dev/sda6
e2fsck -f /dev/sda6

同时在fstab下重新设定一下,在defaults之后增加

defaults,data=writeback,noatime,nodiratime

重启之后,在使用dumpe2fs查看,若没有了,那说明已经把jbd关闭了。

如果使用tune2fs时候,提示disk正在mount,如果是非系统盘下,你可以使用

fuser -km /home #杀死所有使用/home下的进程
umount /dev/sda6 #umount

之后在使用上面的命令进行移除has_journal

你现在在google上搜索“jbd2/sda1-8 high io”,仍然没有一个完整的解决方案,希望这文章能帮到你。

如何找出僵死进程的父进程

今天在查看进程的时候,看到无数个cat,就像这样
Screen Shot 2015-03-24 at 23.14.53

然后我killall杀掉进程后变成这样:

Screen Shot 2015-03-24 at 23.16.09

但这个时候死活杀不掉了。。这是为毛??接下来我只能通过查看进程状态才行了,如下:

> cat /proc/32741/status                                                                                                      
Name:	cat
State:	Z (zombie)
Tgid:	32741
Ngid:	0
Pid:	32741
PPid:	32710
TracerPid:	0
Uid:	1000	1000	1000	1000
Gid:	100	100	100	100
FDSize:	0
Groups:	2 7 50 91 92 93 95 96 100
Threads:	1
SigQ:	27/63909
SigPnd:	0000000000000000
ShdPnd:	0000000000004000
SigBlk:	0000000000000000
SigIgn:	0000000000000000
SigCgt:	0000000180000000
CapInh:	0000000000000000
CapPrm:	0000000000000000
CapEff:	0000000000000000
CapBnd:	0000003fffffffff
Seccomp:	0
Cpus_allowed:	ff
Cpus_allowed_list:	0-7
Mems_allowed:	00000000,00000001
Mems_allowed_list:	0
voluntary_ctxt_switches:	2
nonvoluntary_ctxt_switches:	1

查出PPid,就是parent pid(父进程id),有了这个PPid,再查出导致此问题的进程,把它kill掉即可!

> cat /proc/32710/status                                                                                                     
Name:	chrome
State:	S (sleeping)
Tgid:	32710
Ngid:	0
Pid:	32710
PPid:	1
TracerPid:	0
Uid:	1000	1000	1000	1000
Gid:	100	100	100	100
FDSize:	256
Groups:	2 7 50 91 92 93 95 96 100
VmPeak:	  341320 kB
VmSize:	  341080 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	   47000 kB
VmRSS:	   47000 kB
VmData:	    1660 kB
VmStk:	     136 kB
VmExe:	   90652 kB
VmLib:	   60344 kB
VmPTE:	     464 kB
VmSwap:	       0 kB
Threads:	1
SigQ:	27/63909
SigPnd:	0000000000000000
ShdPnd:	0000000000000000
SigBlk:	0000000000000000
SigIgn:	0000000000000000
SigCgt:	0000000180000000
CapInh:	0000000000000000
CapPrm:	0000000000000000
CapEff:	0000000000000000
CapBnd:	0000003fffffffff
Seccomp:	0
Cpus_allowed:	ff
Cpus_allowed_list:	0-7
Mems_allowed:	00000000,00000001
Mems_allowed_list:	0
voluntary_ctxt_switches:	261533773
nonvoluntary_ctxt_switches:	45982
> killall chrome

查出来的结果!居然是chrome!!

Nginx porxy的一些是使用总结

一、前言

Nginx的Proxy功能很强大,可以做负载均衡,可以做反向代理,可以做页面缓存等等等功能。今天就来详细说一下在我使用的一些经验之谈。也许里面就有所需要的。

Nginx的porxy默认就是自带的,无须任何第三方的模块就可以直接使用,至于nginx的配置以及安装,直接google查一下,相关的文章非常之多。

二、反向代理

1. proxy_pass

指定nginx需要代理谁。语法: proxy_pass URL。作用域在location。首先我们可以来尝试一下,将设你已经有了一个网站 http://a.com,但是我需要http://b.com访问相同的a.com。这个时候你可以这样,

server {
   listen 80;
   server_name b.com;
   index index.html;
   location / {
     proxy_pass http://a.com;
   }
}

现在你访问的b.com就是nginx把a.com反向代理回来的结果。这个时候,你需要问,我程序在a.com需要获得用户的IP地址这些,全是b.com的地址呀。那这个时候就需要下面一个命令了。

2. proxy_set_header

发送给原服务器的时候增加或者修改请求头的信息。 语法: proxy_set_header key value。作用域在location。

proxy_set_header        Host            $host;
proxy_set_header        X-Real-IP       $remote_addr;
proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

把这3行加入到刚刚前面的配置下面,这时候a.com就能获得真实的用户IP地址了。

三、负载均衡

网站发展初期可能只有一台服务器,但是随着你的业务增长,你的服务器越来越多。这时候,你需要服务器能智能的分配用户到不同的服务器上。现有方式的有两种,第一种通过DNS,第二种就是我们接下来要说的nginx负载均衡了。

1. upstream
Nginx的upstream通proxy一样,默认就自带了。通过upstream他将会智能的分配后台的服务器。首先我们看一下配置

upstream backend {
    ip_hash;
    server backend1.example.com       weight=5;
    server backend2.example.com:8080;
    server backup1.example.com:8080   backup;
    server backup2.example.com:8080   backup;
}

server {
 listen 80;
 server_name a.com;
 index index.html;
 location / {
  proxy_pass http://backend; #这里填的就是upstream。必须要有http头
  proxy_set_header        Host            $host;
  proxy_set_header        X-Real-IP       $remote_addr;
  proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
 }
}

现在你访问a.com,nginx将会自动向你分配一台服务器为你服务。可能上面这些配置你看得一头雾水,下面将会一一进行详解。
如何添加负载均衡呢? 通过upstream创建, 语法 upstream NAME。

1.1 server
语法: server address [parameters]
将指定的服务器绑定在负载均衡上,可以使用网址、ip地址或者unix://地址。如果没有特别指定端口号的话,默认就为80。就如上面backup1.example.com:8080 和 backend1.example.com。 一个是指向8080端口,一个是指向80端口。

parameters参数详解:
1.1.1 weight=number
服务器权重,默认为1。值越大被访问的几率也就越大。

1.1.2 max_fails=number
允许最大请求失败数,默认为1。当超过最大次数时,将会在proxy_next_upstream设定的错误。

1.1.3 fail_timeout=time
在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。

1.1.4 backup
预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。

1.1.5 down
表示当前的server暂时不参与负载均衡。只作用于ip_hash轮询。

另外一些非常用的参数:
1.1.6 max_conns=number
设定单台服务器的最大连接数(从1.5.9版本生效)。默认为0, 0表示无连接数限制。

1.1.7 resolve
监控域名地址的变化,将会自动更改解析地址,不需要重启服务器。(从1.5.12版本生效)。特别要说明的是,如果要设定resolve,必须要设定在http作用域范围内。

http {
    resolver 10.0.0.1;
    upstream u {
        zone ...;
        ...
        server example.com resolve;
    }
}

1.1.8 route=string
设定服务器的路由名称

1.1.9 slow_start=time
设定一个恢复正常的服务器从0到设定的weight值所需的时间。主要是针对 服务器挂了重启,访问过慢等等情况。默认为0,禁用。

1.2 负载均衡的分配方式
nginx有多种负载均衡的方式。在默认情况下是使用轮询的方式,即通过weight值来轮询访问。第二种为ip_hash,每个请求按访问IP的hash结果分配,这样来自同一个IP的访客固定访问一个后端服务器,有效解决了动态网页存在的session共享问题。

其余还有health_check, keepalive等等。详细可以预约官方文档: http://nginx.org/en/docs/http/ngx_http_upstream_module.html#health_check

四、页面缓存

说完负载均衡,现在来说说页面缓存。Nginx的页面缓存功能与专业的(squid)web缓存器来比一点也不差。当然配置起来也有点小麻烦。Nginx的proxy默认请下是没有任何配置的所以,你首先要指定缓存规则,缓存的路径等等信息。
1. proxy_cache_path PATH [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time];

PATH缓存的目录,levels参数指定缓存的子目录数。levels指定目录结构,可以使用任意的1位或2位数字作为目录结构,如 X, X:X,或X:X:X 例如: “2”, “2:2”, “1:1:2“,但是最多只能是三级目录。 所有活动的key和元数据存储在共享的内存池中,这个区域用keys_zone参数指定。name指的是共享池的名称,size指的是共享池的大小,可以使用k,m,g。如果在inactive参数指定的时间内缓存的数据没有被请求则被删除,默认inactive为10分钟。一个名为cache manager的进程控制磁盘的缓存大小,它被用来删除不活动的缓存和控制缓存大小,这些都在max_size参数中定义,当目前缓存的值超出max_size指定的值之后,超过其大小后最少使用数据(LRU替换算法)将被删除。

2. proxy_cache_key
设定了缓存路径,接下来就需要缓存key,避免数据重复。默认为$scheme$proxy_host$request_uri 。 你可以添加nginx下的各种参数来组合不同的key值

3. proxy_cache
设置一个缓存区域的名称,一个相同的区域可以在不同的地方使用。
在0.7.48后,缓存遵循后端的”Expires”, “Cache-Control: no-cache”, “Cache-Control: max-age=XXX”头部字段,0.7.66版本以后,”Cache-Control:“private”和”no-store”头同样被遵循。nginx在缓存过程中不会处理”Vary”头,为了确保一些私有数据不被所有的用户看到,后端必须设置 “no-cache”或者”max-age=0”头,或者proxy_cache_key包含用户指定的数据如$cookie_xxx,使用cookie的值作为proxy_cache_key的一部分可以防止缓存私有数据,所以可以在不同的location中分别指定proxy_cache_key的值以便分开私有数据和公有数据。
缓存指令依赖代理缓冲区(buffers),如果proxy_buffers设置为off,缓存不会生效。

注意: 如上面所说,nginx是根据expires,max-age等信息来进行缓存的,如果你需要强制缓存的话,你可以使用proxy_ignore_headers指令,强制进行缓存。

4. proxy_cache_valid
设定缓存的时间。例如对应200 10m, 对应404 1h 写法如下:

proxy_cache_valid 200 10m;
proxy_cache_valid 404 1h;
proxy_cache_valid any 1d;

5. proxy_cache_use_stale , proxy_next_upstream
设定下次更新缓存的触发条件。

6. $upstream_cache_status
在配置底部增加一条set_header X-Cache $upstream_cache_status 这时候你访问页面的时候,就可以了解当前页面是否被nginx缓存成功。一共有多种状态:MISS, EXPIRED, HIT

需要了解更多信息,可以仔细查看官方的proxy文档,文档是介绍指令的方式来说明的,因此有些你需要的东西,可能要花一定的时间全部看完,才知道。就如怎么强制进行缓存。我是看了四五遍之后才发现,可以如此干。

Nginx还有很多功能还没发掘,需要在实际使用中好好研究。会有更多收获。

定时备份mysql数据

#!/bin/bash

DB_USER=root
DB_PASSWD=""
#需要备份的数据库名
DATABASES="bigamer bigamer_ucenter bigamer_anwsion bigamer_passport"
BACKUP_DIR="/home/backup/mysql/"
DATE=`date '+%Y%m%d'`
DUMPFILE=$DATE.sql
ARCHIVEFILE=$DUMPFILE.tar.gz
DUMP_ARGS="-u $DB_USER -p $DB_PASSWD --add-drop-table --add-drop-database -B $DATABASES"
DUMP_BIN=`which mysqldump`

if [ ! -d $BACKUP_DIR ]; then
mkdir -p "$BACKUP_DIR"
fi

cd $BACKUP_DIR

$DUMP_BIN $DUMP_ARGS > $DUMPFILE

if [[ $? == 0 ]]; then
tar czf $ARCHIVEFILE $DUMPFILE
    rm -f $DUMPFILE
fi

#清理五天前备份的数据
find $BACKUP_DIR -name "*.sql.tar.gz" -type f -mtime +5 -exec rm {} \; > /dev/null 2>&1

echo "Backup Process Done"

Apache mod_ssl通过PoisitveSSL认证


由于前几天国内大断网之后, 现在安装的三方twitter客户端dabr和twip, 每次都会重置链接. 通过测试服务器上设定ssl链接后, 就不会被我们伟大的GFW重置链接. 但没有第三方机构认证的ssl, 在twitter for iphone客户端上将会无法使用. 首先我尝试了免费的startssl, 但是无法进入控制面板. 然后就在cheapssls.com找到了一个单域名ssl认证, 每年只需要$8. (这里的单域名, 只能用在一次域名地址上, 比如你注册的是wolftankk.com, 那么用在t.wolftankk.com上, 浏览器会警告你证书错误). 聊了这么多, 我们来讲讲具体步骤.

在此之前请确保mod_ssl模块已经加载.

生产.csr文件与.key文件

openssl req -nodes -newkey rsa:2048 -keyout server.key -out server.csr

根据选项输入国家, 城市, 邮件地址以及域名地址 (Common Name 域名地址一定要填写正确)
我这里注册的是t.wolftankk.com

在cheapssls上选购poisitiveSSL

然后在选购面板中填写你需要申请的域名地址,email, 电话 以及联系地址.
并且在csr选择 apache + mod_ssl, 并且将你服务器上csr文本内容黏贴在文本框中
在过不了多久, 你就会收到邮件, 此邮件里面包含域名的crt和ca-bundle
将server.key, wolftankk_com.crt, wolftankk_com.ca-bundle 全部放在 apache2/conf目录下

mod_ssl设定

修改mod_ssl配置, 修订apache2/conf/extra/httpd-ssl.conf

Listen 443

AddType application/x-x509-ca-cert .crt
AddType application/x-pkcs7-crl .crl

SSLPassPhraseDialog builtin

SSLSessionCache "shmcb:/usr/local/apache2/logs/ssl_scache(512000)"
SSLSessionCacheTimeout 300

SSLMutex "file:/usr/local/apache2/logs/ssl_mutex"

同时将下面的这段全部注释.

设定httpd-vhost.conf

NameVirtualHost *:443

ServerAdmin wolftankk@gmail.com
DocumentRoot "/home/htdocs/dabr/wwwroot"
ServerName t.wolftankk.com:443
ErrorLog "/home/htdocs/dabr/logs/error.log"
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLProtocol all -SSLv2
#poisitiveSSL 发给你的crt文件
SSLCertificateFile "/usr/local/apache2/conf/wolftankk_com.crt"
#生产server.key文件
SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"
#poisitiveSSL 发给你的ca-bundle
SSLCertificateChainFile "/usr/local/apache2/conf/wolftankk_com.ca-bundle"
SSLCACertificateFile "/usr/local/apache2/conf/wolftankk_com.ca-bundle"
SSLOptions +StdEnvVars

SSLOptions +StdEnvVars

BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0

CustomLog "/home/htdocs/dabr/logs/access.log" \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

设定完之后, 重启apache, 现在你访问t.wolftankk.com 就不会在显示不信任的认证, 在浏览器的地址栏上会显示第三方认证的标志.

现在你就不怕你搭建的第三方twitter客户端被重置链接了.

rsync配置以及一些小提示

最近搞镜像同步, 用到了rsync. 这里做一些简单的备忘记录.

Rsyncd

1 安装
在服务器上安装rsync,
在debian, ubuntu 服务器上可以使用apt-get install rsync
在centos, redhat 服务器上可以使用yum install rsync
或者直接下载rsync源代码: http://www.samba.org/ftp/rsync/rsync-3.0.9.tar.gz (目前最新版本3.0.9)
然后./configure and make and make install

2 配置rsyncd.conf

uid = nobody
gid = nobody
use chroot = no
max connections = 25
read only = yes
port = 873
[MODNAME]
path = /home/htdocs/res
comment = Website static resource (~30G)
list = yes
auth users = wolftankk
ignore errors
secrets file = /etc/rsyncd/MODNAME.scr
exclude = tmp/

然后设置MODNAME.scr
[注意] 一定要将MODNAME.scr 设置为600属性

wolftankk:mypass

更具体的配置 可以参考http://www.samba.org/ftp/rsync/rsyncd.conf.html

3 启动

/usr/bin/rsync --daemon --config=/etc/rsyncd/rsyncd.conf

将此命令加入启动脚本中, 服务器将会在每次启动时候自动启动rsyncd

Rsync

在镜像服务器上设置同步

测试链接

rsync -avzP wolftankk@172.16.1.30::
如果链接成功, 将会列出此服务器上的 模块以及注释, 如下

[MODNAME]
comment = Website static resource (~30G)

[备注]
-a参数: 相当于-rlptgoD,-r 是递归 -l 是链接文件,意思是拷贝链接文件;-p 表示保持文件原有权限;-t 保持文件原有时间;-g 保持文件原有用户组;-o 保持文件原有属主;-D 相当于块设备文件

在使用-a参数的时候, 会将服务器A的owner以及group同步到本地, 有可能会导致你镜像文件的读写权限导致问题.
我们可以使用–no-OPTIONS 参数,比如我不需要同步文件(夹)的owner和group, 那么加入参数 –no-o 和 –no-g

屏蔽列表, 屏蔽方式用两种一种是直接写在配置里面, 另一种是写在一个但是的配置文件中.
1. exclude
不包含文件夹 –exclude=tmp/
不包含文件 –exclude=include/database.php

2. exclude-from
vim /etc/rsync.ignore

tmp/
include/database.php
download/test/*
static/css/*.sass

设置cron

* */1 * * * /usr/bin/rsync -az --password-file=/etc/rsync.pass --exclude-from=/etc/rsync.ignore --no-o --no-g wolftankk@172.16.1.30::MODNAME /home/htdocs/res

每小时同步一次.

在rsync.pass种设定密码, 并且必须要设置为600权限

mypass

详细参数可以参考: http://www.samba.org/ftp/rsync/rsync.html

500,000 requests/sec – Modern HTTP servers are fast

翻译自: http://lowlatencyweb.wordpress.com/2012/03/20/500000-requestssec-modern-http-servers-are-fast/

现在的HTTP服务器运行在某些计算上, 表现很差, 连接过长, 连接时间过慢, 等等原因. 下面一张图就是在Unbutu系统中安装了Nginx 1.0.14, 测试并发访问index.html的一些数据.以及下表的测试环境.

软件

这里只讨论Linux, 首先我们需要设置下系统网络层的参数

echo "2048 64512" > /proc/sys/net/ipv4/ip_local_port_range
echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
echo "10" > /proc/sys/net/ipv4/tcp_fin_timeout

echo "65536" > /proc/sys/net/core/somaxconn
echo "65536" > /proc/sys/net/ipv4/tcp_max_syn_backlog

echo "262144" > /proc/sys/net/netfilter/nf_conntrack_max

HTTP服务器为nginx 1.0.14, configure & build

worker_processes     16;
worker_rlimit_nofile 262144;

daemon off;

events {
  use epoll;
  worker_connections 16384;
}

error_log error.log;
pid /dev/null;

http {
  sendfile   on;
  tcp_nopush on;

  keepalive_requests 100;

  open_file_cache max=100;

  gzip            off;
  gzip_min_length 1024;

  access_log off;

  server {
    listen *:8080 backlog=16384;

    location / {
      root   html;
      index  index.html;
    }
  }
}

硬件部分

是双核Intel至强5670, 24G内存. The X5670 has 6 cores @ 2.93 GHz, 2 threads per core, /proc/cpuinfo shows 24 CPUs.

Cisco catalyst configuring VLANs

一. 设置当前交换机为server模式
switch>enable
switch# configure t
switch(config)>vtp mode server
switch(config)>exit

二. 删除原先的vlan
switch>enable
switch# configure t
switch(config)>no vlan VLAN-ID
switch(config)>exit

三. 增加一个新的vlan
switch>enable
switch# configure t
switch(config)>vlan VLAN-ID
switch(config)>name VLAN-NAME
switch(config)>exit

比如

Switch# configure terminal
Switch(config)# vlan 20
Switch(config-vlan)# name test20
Switch(config-vlan)# end

四. 分配一个到指定的vlan

Switch# configure terminal 
Enter configuration commands, one per line. End with CNTL/Z.
Switch(config)# interface gigabitethernet0/1 
Switch(config-if)# switchport mode access 
Switch(config-if)# switchport access vlan 2
Switch(config-if)# end 

五. 重载配置

copy running-config startup-config

六. 备忘录
vlan的id 比如10 20 30,这些你在网关上要对应,我这是使用的routeros。这样才能起到一个局域网内有不同的网段以及网段之间的阻隔。

Debina6 升级安装python2.7

只要在/etc/apt/source.list中加入
deb http://ftp.cn.debian.org/debian/ unstable main contrib non-free

apt-get clean
apt-get update

然后就可以安装python2.7 vim7.3这些最新的软件了

The bash script of downloading the graphics programmming book

Download the <>, by Micheal Abrash

wget http://twimgs.com/ddj/abrashblackbook/gpbb{0..70}.pdf

or

curl -O http://twimgs.com/ddj/abrashblackbook/gpbb{0..70}.pdf

also, you can use the command below:

wget -r -l1 -H -t1 -nd -N -np -A.pdf -erobots=off http://drdobbs.com/high-performance-computing/184404919