blog迁移记录

根据前面blog说的ec2的低级错误造成的重大损失后,马上也想到EC2也快过期了就单独新买一个VPS。今天上午折腾了一下终于把数据都迁移好了。
其实迁移blog主要是把db数据备份好。然后图片文件什么都通通打包下来。我是把blog目录直接整体打包了(包括图片什么的)。DB数据的备份就是使用的
tools.php?page=wp-db-backup进行的。之前是设置了每周备份发送到邮箱里。昨天马上又保存了一份在自己电脑上面。然后把blog目录直接打个tgz包放到新的机器上面。
1.重新配置lnmp环境
1.1安装mysql
aptitude install mysql-server mysql-client
安装的时候会设置一下mysql的密码,自己记住就行。
1.2安装php5-fpm
aptitude install php5-fpm php5-mysql nginx-full
[text]
/etc/php5/fpm/pool.d/www.conf修改
user = www-data
group = www-data
listen.owner = www-data
listen.group = www-data
listen = /var/run/php5-fpm.sock #我是监听的sock形式
/etc/init.d/php5-fpm restart
[/text]
1.3 nginx配置
nginx.conf 里面改动比较小,加
client_max_body_size 50m;#防止上传文件的时候超过大小
keepalive_timeout 5; #把这个减小一点,主要是机器配置也不好。
gzip on;#gzip什么的开启节省带宽,也能提高速度
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
/etc/nginx/sites-enabled/default 修改的多些,因为我申请了IPV6的地址,所以装B一把也把V6的监听起来。
server段先定义一下限流的zone
limit_req_zone $binary_remote_addr zone=gnuers:10m rate=30r/s;
listen 80;
listen [::]:80 ipv6only=on;
location php直接这样改改,加了防止盗链什么的,还限制了访问的host。
[text]

location ~ \.php$ {
if ( $host !~* blog.gnuers.org ){
rewrite ^ https://www.google.com permanent;
}
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
#
# # With php5-cgi alone:
# # With php5-fpm:
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_intercept_errors on;
fastcgi_buffers 1024 4k;
fastcgi_buffer_size 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_send_timeout 60;
fastcgi_read_timeout 60;
fastcgi_connect_timeout 60;
}
location ~* \.(gif|jpg|png|swf|flv)$ {
valid_referers none blocked blog.gnuers.org ;
if ($invalid_referer) {
rewrite ^ http://www.google.com/ permanent;
}
expires 20m;
}
[/text]
这样基本能打开页面了,不过db还没有导入呢

1.3导入DB

mysqldump -h localhost -u root -p 输入密码后登陆mysql,
[text]
create database wordpress;
use wordpress;
set names utf8; #一定记得加这个,我之前么有加这个直接 mysql -h localhost -u root -pxxxxx wordpress <wordpress_wp_backup.sql
#后中文乱码
source wordpress_wp_backup.sql ;
[/text]
另外还需要设置一下权限让之前的用户能访问操作几个表
GRANT ALL PRIVILEGES ON wordpress.* TO ‘wp_admin’@’localhost’ IDENTIFIED BY ‘password1’;
GRANT ALL PRIVILEGES ON wordpress.* TO ‘wp_admin’@’localhost.localdomain’ IDENTIFIED BY ‘password1’;
FLUSH PRIVILEGES;
配置好后就可以访问了。
有了之前的教训,我也在dnspod上把免费的监控开启了。这样当机器有问题的时候可以直接发送短信和邮件提醒我。以免自己平时一直不用,机器出了问题都不清楚。

发表在 nginx, Web server | 留下评论

nginx的upstream里不能支持长连接的排查

最近在对比apache和nginx放jboss前面的性能。发现我配置的nginx 对后端server不能使用长连接去连。具体的就是抓包吧:

tcpdump -i lo port 7002 and ‘tcp[tcpflags] & (tcp-syn|tcp-fin) !=0 ‘ -nn

可以看到每个请求完毕后连接都关闭了。
然后抓包搞一晚上,试过N个版本排查了N久,后恰好看文景同学在线就咨询了一下他。我之前的配置文件是:

[text]
upstream jboss {
server 127.0.0.1:7002;
keepalive 10;
}
………….
proxy_set_header Connection "";
proxy_http_version 1.1;
sendfile on;
rewrite ^$ /index.html permanent;
location / {
index index.html index.htm;
proxy_pass http://jboss;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_intercept_errors on;
proxy_connect_timeout 5s;
proxy_read_timeout 10s;
proxy_send_timeout 5s;
proxy_buffer_size 16k;
proxy_buffers 8 64k;
proxy_busy_buffers_size 128k;

}
[/text]

文景提醒我说proxy_set_header需要配置在一起才行,试过把 proxy_set_header Connection “”;放到location里面后果然就OK了。
当然,也可以把这些都直接放在server段,但是注意不要再在location短去设置httpd头.WIKI上的说明是
proxy_set_header directives issued at higher levels are only inherited when no proxy_set_header directives have been issued at a given level.

http://wiki.nginx.org/HttpProxyModule#proxy_set_header

发表在 nginx | 留下评论

记一次乌龙事件

去年5月的时候用信用卡申请了amazon的免费的EC2用来随便玩玩。平时其实就挂个blog,也不怎么用(包括不怎么用于翻墙)。最近总是登录不上,昨天无意间看到了流量监控,才发现进出口的带宽都非常大,峰值的时候到了150Mpbs,然后看了一下历史记录发现大概已经一周左右了。
QQ截图20130309123233

QQ截图20130309123325

然后第一感觉是不是被DDOS了,但是DDOS的话出去的流量不会这么大。我就把22和80端口以外的端口都关闭了。流量立马下降了,而且机器也能登录了。
top看了一下发现squid3的进程耗内存非常多。我才想起年前配置过一次squid做反向代理时没有设置密码,立即想到流量费会不会超过。
不幸的是本月账单上已经显示使用了$56了,赶紧连夜买了一个30多块钱一个月的OpenVZ的VPS,然后把数据迁移下来,把EC2停掉。今天看了一下账单都用了$61了。

就当吸取一个小的教训吧。

发表在 Admin | 留下评论

dnsmasq的rebind_protection引发的问题

在之前写到过OpenWrt的lan端不能正常解析公司内部域名的问题,并通过在dhcp里让用户的dns设置为指定的DNS服务器的方式得到了临时的解决。
但是在路由器自身上还是解析不了内部的域名。今天看了一下实际生效的配置文件里面有一项:stop-dns-rebind,然后在http://wiki.openwrt.org/doc/uci/dhcp查到了
rebind_protection boolean no 1 –stop-dns-rebind
Enables DNS rebind attack protection by discarding upstream RFC1918 responses
rebind_localhost boolean no 0 –rebind-localhost-ok
Allows upstream 127.0.0.0/8 responses, required for DNS based blacklist services, only takes effect if rebind protection is enabled
rebind_domain list of domain names no (none) –rebind-domain-ok
List of domains to allow RFC1918 responses for, only takes effect if rebind protection is enabled
这几个选项的含义,直接在配置里去掉了这项之后,并且取消了之前在dhcp里配置的 list ‘dhcp_option’ ’6,DNS1,DNS2′,重启路由器后也可以正常通过路由器的dnsmasq提供的解析了。

1

发表在 OpenWrt | 留下评论

TP-LINK 740N复活记

由于在公司直接连接无线时访问内部资源还需要拨VPN才行,非常不方便。所以我一直放了一个路由器插网线做802.1X认证。现在用的这个是在淘宝上30多块钱买的一个旧的TP-LINK的740N V4。由于之前这个路由器出厂时的CPU频率被限制在350Mhz,所以我当时是刷过别人改过uboot的741N固件(740和741对应的版本基本是可以通刷的),刷了之后恢复了ar7240默认的400Mhz。
之前路由器LAN-WLAN的速度问题一直困扰着我,不过反正就平时办公用一下,所以也无所谓,再慢也能有800KB/S左右的速度,直接测试WAN->WLAN的带宽也能跑到30Mbps多点。今天想着刷一下新版本的OpenWrt直接就下了个741n V4的OpenWrt固件,结果直接刷砖了。后来仔细看了一下WIKI,才发现刷的是AR9330才能用的固件。。

回家后找出电烙铁和TTL线,参考之前网上找的TTL接线图。
Image
把TTL线焊好,另外windows上下了个tftp32,正确的740N v1的固件放在目录下就可以开始修复了:
1. tftpboot 0x80000000 740v1.bin #把固件下载到内存中
2. erase 0x9f020000 +0x3c0000 #把flash除去uboot的那部分擦除,后面0x3c0000为固件大小
3. cp.b 0x80000000 0x9f020000 0x3c0000 #写入固件。
4.输入bootm就能启动了

正好晚上也有时间,我把T530和X220一个连LAN口,另外一个无线连接路由器,测试了一下LAN-WLAN的速度,确实比较搓

HT20
然后搜了下:http://wiki.openwrt.org/doc/uci/wireless?s[]=noscan

40 MHz channel (300 Mbps)
Stuck at 130Mbps? Get 300Mbps! Note: this violates regulatory requirements.

Edit the file /etc/config/wireless, and restart the wifi AP by executing the following commands…

uci set wireless.radio0.htmode=HT40+ # or: HT40- if using channel 11
uci set wireless.radio0.noscan=1
uci commit wireless; wifi
Note that option ‘htmode’ should be set to either HT40+ (for channels 1-7) or HT40- (for channels 5-11). You have to use WPA2 encryption with AES.

自己修改了一下配置

config wifi-device ‘radio0’
option type ‘mac80211’
option macaddr ‘e0:15:c4:2b:a0:71′
option hwmode ’11ng’
list ht_capab ‘SHORT-GI-40’
list ht_capab ‘TX-STBC’
list ht_capab ‘RX-STBC1’
list ht_capab ‘DSSS_CCK-40’
option channel ‘6’
option country ‘US’
option txpower ’27’
option noscan ‘1’
option htmode ‘HT40+’
改成使用40Mhz的频段,并且加上noscan选项。
再测试一下就能跑出正常的水平了

HT40

noscan只有在40M频段才有意义,在20M频段的话这个选项的没有意义。

发表在 OpenWrt | 留下评论

fcitx在gnome3下的安装

fcitx总体来说还是很不错的一个中文输入法。不过虽然很简单的一个东西,每次安装都有点这样那样的问题。
要选的包有fcitx,fcitx-config-gtk2,fcitx-ui-classic,fcitx-frontend-gtk2,fcitx-frontend-gtk3,im-switch.
每次安装后运行一下im-switch选一下fcitx。然后需要注意重启一下dbus才行。

发表在 OS | 留下评论

apache的参数调整

apache+jboss是公司应用的基本结构。但是很多参数一直没有调整过。之前做个一些调优,把很多关键的参数看了一下,单独注释了。
Timeout 180 #Timeout主要是定义了在处理一个请求时的多种超时时间,默认是300s。我们需要关注意的主要是2个。
#一个是当读缓冲区为空时,等待client段发送一个包的超时时间。另外就是当发送缓冲区满的时候,
#向客户端发送一个包后的等待确认时间。Timeout与单次请求的完成总时间毫无关系。
KeepAlive On #是否启用KeepAlive,由于应用放spanner后端,开启后可以使得spanner能和应用保持持续的连接,提高一定性能。
MaxKeepAliveRequests 100 #单个KeepAlive的连接能处理的最大请求数,可以适当调高,提高单个连接复用的效率。
KeepAliveTimeout 3 #单个keepalive的连接在指定时间内如果没有请求,就进行回收。


StartServers 10 #初始的工作进程数量
ServerLimit 50 #工作进程的最大数量
MaxClients 2500 #最大的并发访问数量,不能超过ServerLimit*ThreadsPerChild
MinSpareThreads 50 #最小的闲置线程数
MaxSpareThreads 200 #最大的限制线程数
ThreadsPerChild 50 #每个进程的最大线程数,需要注意32位的系统单个进程的能启动的线程数小于384.
MaxRequestsPerChild 10000 #每个进程能处理的最大请求数。

# mod_jk(Apache Tomcat)

worker.list=local #定义worker的名称,如果有多个可以用逗号隔开(多个时候就是一个apache对多个tomcat做负载均衡)
# 对于每个worker的属性定时使用这样的模式: worker..=
worker.local.type=ajp13 #定义协议名称
worker.local.host=localhost #因为是连本地的jboss,所以直接写localhost就行。
worker.local.port=7001 #本地tomcat ajp的端口
worker.local.lbfactor=50 #单个worker的权重,在有多个worker做负载均衡的时候此项才会有意义
worker.local.cachesize=100 #单个进程对后端的连接被当初一个连接池对待,每个进程的链接池的连接数上限。需要注意最好不要超过apache里每个进程的线程数
worker.local.cache_timeout=600 #当cachesize里连接池内的连接在关闭前被保留的时间。
worker.local.socket_keepalive=1 #在apache和后tomcat间启用tcp的KEEP_ALIVE属性,主要是在当tomcat和jk直接有防火墙的时候会把不活动的连接关闭掉,此时可以通过设置此选项。
worker.local.recycle_timeout=300 #作用其实和cache_timeout类似,但是在non-cache模式下也能使用。
#当某个请求不在一定时间内不活跃后,告诉apache关闭该ajp连接,降低此值能大大减少后端tomcat的负担。

贴一个自己改过的配置:
[text]
Timeout 10
KeepAlive On
MaxKeepAliveRequests 1000
KeepAliveTimeout 5

<IfModule worker.c>
StartServers 10
ServerLimit 50
MaxClients 2500
MinSpareThreads 50
MaxSpareThreads 200
ThreadsPerChild 50
MaxRequestsPerChild 10000
</IfModule>

workers.properties:
# mod_jk(Apache Tomcat)

worker.list=local

worker.local.type=ajp13
worker.local.host=localhost
worker.local.port=7001
worker.local.lbfactor=50
worker.local.cachesize=25
worker.local.cache_timeout=15
worker.local.socket_keepalive=1
worker.local.recycle_timeout=10
[/text]

发表在 Web server | 留下评论

使用nginx做缓存服务器

nginx做cache其实也比较简单。配置项非常少
[text]

#user nobody;
worker_processes 1;

error_log logs/error.log;
pid logs/nginx.pid;

events {
worker_connections 65535;
}

http {
include mime.types;
default_type application/octet-stream;
underscores_in_headers on;
log_format main ‘$http_orig_client_ip $remote_addr $host – $remote_user [$time_local] "$request" ‘
‘$status $body_bytes_sent "$http_referer" ‘
‘"$http_user_agent" "$http_x_forwarded_for"’;

access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
proxy_cache_path /home/admin/nginxcache/one levels=1:2 keys_zone=blogone:10m inactive=5m max_size=100m;
# proxy_cache_path /dev/shm/nginxcache/one levels=1:2 keys_zone=blogone:10m inactive=5m max_size=100m;
#5分钟不使用的会被删除,最大100M

server {
listen 80;
server_name localhost;
charset gbk;
access_log logs/cache.access.log main;
keepalive_requests 1000;
client_max_body_size 50m;
############gzip ##################
gzip_disable "msie6";
gzip_comp_level 7;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 1k;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text /javascript;
######## proxy ####################
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_intercept_errors on;
proxy_set_header Host $http_host;
proxy_set_header ORIG_CLIENT_IP $remote_addr;
proxy_read_timeout 5;
proxy_send_timeout 3;
proxy_connect_timeout 2;
##########cache#################
proxy_cache_methods GET HEAD;
proxy_cache_min_uses 2;#被访问次数大于2个才会缓存
proxy_cache_valid 302 5m;
proxy_cache_valid 200 20m;
proxy_cache_key "$scheme$host$request_uri";
proxy_cache blogone;#使用缓存空间
location / {

proxy_pass http://blog;
}
location ~* \.(gif|jpg|png|swf|flv)$ {

expires 10m; #图片缓存10分钟
proxy_pass http://blog;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
upstream blog {
server blog.gnuers.org:80;
keepalive 1;

}
}
[/text]

如果是想把内容放内存,可以把缓存的路径设置到shm里面。

发表在 nginx | 留下评论

网站负载均衡与高可用方案的选型

负载均衡与高可用本来是个很大的话题,可以做的方式多种多样,我只是把自己熟悉一点的简单讲一些。

bind
1. 其实最原始的负载均衡就是在DNS上直接做多个A记录,这样用户解析网站域名的时候就会随机解析为我们设置的一个A记录的IP。但我们不能改变2个IP被解析的概率,如果2个机器的负载能力不同,那这种方式就欠妥了。
2. 既然直接A记录不好控制比例,那么我们可以通过bind的view来根据查询源IP做解析。比如把网通的用户解析为网通机房的IP,把电信的用户解析为电信IP,具体的策略设置非常灵活,根据实际情况而定。
对于DNS服务器自身的高可用和负载均衡可以使用keepalived打包完成。如果有条件的可以多个DNS机器跑OSPF集群解决。

LVS

一般大家使用keepalived来管理lvs,并能借助keepalived支持的vrrp协议实现HA。对于CDN节点这种类型的话,非常适用与LVS(DR)+[haproxy+squid],因为单个几点的机器比较少,网络结构不会太负载,而流量又会非常大。直接在一个万兆交换机下挂10多个机器,其中2个做LVS(主/备),另外的所有机器同时部署haproxy和squid,所有机器的squid配置都一样,同时上面跑的haproxy的配置也都一样,backend里面把所有的机器都加进去,这样可以做采用URL hash算法来提高缓存的命中率。但是需要注意此种模式,交换机下的流量会比较大,比不使用haproxy会翻倍,一定要保证交换机的背板带宽够用。
LVS相对其他很多负载均衡软件的优势时可以支持UDP,而且DR模式和TUN模式的时候对于大部分业务类型只有用户的请求经过LVS机器,后端服务器响应的内容都是直接返回给用户,所以不会像NAT模式进出的流量都要经过LVS。但是DR和TUN都需要给后端机器绑VIP,比较麻烦。而NAT模式又需要其他机器把LVS机器作为网关,也限制了其使用的范围。相对来说淘宝改的FULLNAT模式部署起来对环境的要求比较低,但是短时间内不会合并到trunk,使用RHEL以外发行版的同学基本不能使用。而且后端机器要获取客户端的IP需要单独安装一个toa的内核模块,因为做了snat后他们只能在一个tcp头的保留字段插入客户的真实IP。

haproxy
haproxy其实是和很成熟的负载均衡软件,4/7通吃,调度算法也非常丰富,配置项目非常多,文档支持也很好,现在也支持了ssl加密了。haproxy因为之前一直采用的tunnel-like模式,所以现在对后端机器开不了keepalive,缺一个非常非常重要的特性。或许在2013年能搞出来。

nginx
nginx作为现在最火的webserver,在做代理方面也非常流行,做ssl加密非常方便,配置比起haproxy更加简单和灵活。但是整体而言,不能做4层的反向代理是个遗憾。负载算法方面nginx的不像haproxy有那么多,不过其实一般大家用的最多的还是简单的轮询,流量特别大的网站都是不可能使用wlc算法的,不然机器启动就直接被打暴了。

haproxy和nginx的高可用都需要借助keepalived来做(需要注意改内核参数使备机能直接监听非本地的IP)。当然,如果单个nginx或者haproxy撑不住,也可以使用2层结构,第一层跑LVS,下面一层跑haproxy或者nginx,不过此时VIP都是绑定在第一层的LVS上面。lvs上频繁修改配置reload还是需要注意,不小心搞挂了就悲剧了。

经常见很多论坛,就两三个机器在折腾LVS,问比如遇到RS上不能访问VIP,或者Director上访问不了VIP这些确实比较蛋疼的问题,基本都是没有仔细搞清楚lvs原理,也没有好好看文档的,对于这种我是建议直接跑个haproxy或者nginx就搞定了。

发表在 Haproxy, keepalived, lvs | 留下评论

分析全站应用的响应时间

因为流量镜像分析的功能还没有做好,目前要统计全站的应用的响应时间就比较麻烦。我直接把做代理的nginx的日志都拷贝出来,然后跑脚本。
由于日志是压缩过的,本来直接perl里面可以使用cpan里的一个gunzip的模块,但是测试后发现性能实在烂的不行,连gunzip速度的1/4都不到。后来直接换成调用pigz多线程解压,虽然pigz在解压时不如在压缩时能体现出多线程优势,但是相对直接gunzip还是快了些,反正机器有的是CPU,主要是磁盘性能不行。
[perl]
#!/usr/bin/perl
use warnings;
use strict;
use IO::Uncompress::Gunzip qw(gunzip $GunzipError);
my %dtimes;
my %dseconds;
my $DEBUG=1;
my @logs;
my $PRE="/home/test/temp";
my $tempfile="$PRE/gunziptemp";
my @time=(1,2,3,4,5,6,7,8,9,10);
opendir my $DIR,"$PRE" or die "open dirctory failed";
while(my $dir=readdir $DIR) {
push @logs,$dir if $dir =~/log.gz/ ;
}
close $DIR;
foreach my $log(@logs) {
print STDERR "analysis $log\n" if ($DEBUG ==1 );
# open my $logfd,"<$PRE/$log" or die "open $log failed\n";
# open my $unziplog,">$tempfile" or die "open unzip file failed\n";
# gunzip $logfd => $unziplog or die "unzip $log failed\n";
`pigz -d -k -c $PRE/$log >$tempfile ` or "unzip $log failed\n";
print STDERR "unzip $log ok \n" if ($DEBUG ==1 );
# close $unziplog;
open my $unziplog,"<$tempfile" or die "open2 unzip file failed\n";
print STDERR "start analysis log\n" if ($DEBUG ==1 );
while(my $line=<$unziplog>) {
my @temp;
my ($domain,$restime);
if($line=~/xxxx.com/) {
@temp=split(/\s+/,$line);
$domain=$temp[7];
$restime=$temp[-1];
next if( $restime !~ /\d+/);
next if( $domain !~ /xxxx.com/ );
$domain=~s/:\d+//;
}
if(defined $domain && defined $restime ){
$dtimes{$domain}++;
my @t=grep { $_ – $restime <0} @time;
foreach my $k(@t){
$dseconds{$domain}{$k}++;
}

}

}
close $unziplog;
# close $logfd;
unlink $tempfile or die "rm $log failed\n";
print STDERR "finish $log analysis\n" if ($DEBUG ==1 );
}
print "domain\t",join(" ",@time),"\n";
foreach my $domain(sort keys%dseconds) {
print "$domain ";
foreach my $t(@time) {;
$dseconds{$domain}{$t} =0 if (!defined $dseconds{$domain}{$t});
my $per=($dtimes{$domain}-$dseconds{$domain}{$t})/$dtimes{$domain}*100;
printf(" %.4f",$per);

}
print "\n";

}

[/perl]

主要是由于日志实在太大了,机器的磁盘有限就200多GB的空间,所有的日志直接解压放不下。由于是单进程串行执行,所以直接线把日志名都放一个列表里面。然后对每个日志进行解压,分析,并把结果放到一个hash里面。我是统计了后端服务器在1-10s内的响应率,grep { $_ – $restime <0} @time直接就能把把响应时间小于分别小于1-10的返回到一个列表里面,一定要避免对于每个时间都重新扫一次日志,那样就慢10倍了。 Screenshot from 2012-12-27 00:08:37

发表在 Perl Script | 留下评论