2015年4月

Docker学习笔记一

docker基本概念

  • images: 镜像,简单理解就是装系统的ISO镜像,images只是binary,是“死”的,加载起来后可以运行
  • container: 容器,由镜像创建的运行实例,就和普通的linux服务一样,可以创建、start、stop、删除。但是每个容器都是彼此独立的,互相不干扰

docker安装

  • 环境: CentOS 6.x
$ sudo yum install docker-io
  • 环境: CentOS 7.x
$ sudo yum install docker
  • 环境: CentOS 5.x

目前尚未发现yum安装,网上关于docker编译安装的资料也不多

- 阅读剩余部分 -

理解HTTP之keep-alive

理解HTTP之keep-alive

在前面一篇文章中讲了TCP的keepalive,这篇文章再讲讲HTTP层面keep-alive。两种keepalive在拼写上面就是不一样的,只是发音一样,于是乎大家就都迷茫了。HTTP层面的keep-alive是我们接触比较多的,也是大家平时口头上的"keepalive"。下面我们就来谈谈HTTP的keep-alive

短连接&长连接&并行连接

再说keep-alive之前,先说说HTTP的短连接&长连接。

  • 短连接

    所谓短连接,就是每次请求一个资源就建立连接,请求完成后连接立马关闭。每次请求都经过“创建tcp连接->请求资源->响应资源->释放连接”这样的过程

  • 长连接

    所谓长连接(persistent connection),就是只建立一次连接,多次资源请求都复用该连接,完成后关闭。要请求一个页面上的十张图,只需要建立一次tcp连接,然后依次请求十张图,等待资源响应,释放连接。

  • 并行连接

    所谓并行连接(multiple connections),其实就是并发的短连接。

- 阅读剩余部分 -

理解TCP之Keepalive

理解Keepalive(1)

大家都听过keepalive,但是其实对于keepalive这个词还是很晦涩的,至少我一直都只知道一个大概,直到之前排查线上一些问题,发现keepalive还是有很多玄机的。其实keepalive有两种,一种是TCP层的keepalive,另一种是HTTP层的Keep-Alive。这篇文章先说说tcp层的keepalive

tcp keepalive

设想有一种场景:A和B两边通过三次握手建立好TCP连接,然后突然间B就宕机了,之后时间内B再也没有起来。如果B宕机后A和B一直没有数据通信的需求,A就永远都发现不了B已经挂了,那么A的内核里还维护着一份关于A&B之间TCP连接的信息,浪费系统资源。于是在TCP层面引入了keepalive的机制,A会定期给B发空的数据包,通俗讲就是心跳包,一旦发现到B的网络不通就关闭连接。这一点在LVS内尤为明显,因为LVS维护着两边大量的连接状态信息,一旦超时就需要释放连接。

Linux内核对于tcp keepalive的调整主要有以下三个参数

1. tcp_keepalive_time

 the interval between the last data packet sent (simple ACKs are not considered data) and the first keepalive probe; after the connection is marked to need keepalive, this counter is not used any further

2. tcp_keepalive_intvl

 the interval between subsequential keepalive probes, regardless of what the connection has exchanged in the meantime

3. tcp_keepalive_probes

 the number of unacknowledged probes to send before considering the connection dead and notifying the application layer

Example

$ cat /proc/sys/net/ipv4/tcp_keepalive_time
  7200
$ cat /proc/sys/net/ipv4/tcp_keepalive_intvl
  75
$ cat /proc/sys/net/ipv4/tcp_keepalive_probes
  9

当tcp发现有tcp_keepalive_time(7200)秒未收到对端数据后,开始以间隔tcp_keepalive_intvl(75)秒的频率发送的空心跳包,如果连续tcp_keepalive_probes(9)次以上未响应代码对端已经down了,close连接

在socket编程时候,可以调用setsockopt指定不同的宏来更改上面几个参数

TCP_KEEPCNT: tcp_keepalive_probes

TCP_KEEPIDLE: tcp_keepalive_time

TCP_KEEPINTVL: tcp_keepalive_intvl

- 阅读剩余部分 -

git merge不同branch文件

平时用git开发过程会有这样一种场景,比如大伙都在branchA上commit,然后有一个临时的需求开了一个branchB,我一个人去那里commit了,大伙还继续在branchA上commit新功能。这时候我需要branchA上的一个新功能(不包含其它未完成的功能)merge到branchB里,也就是说我只需要merge branchA上指定一部分目录或者文件代码。看下面这个例子:

创建branch分支
$ git branch
  * master
$ mkdir dir1
$ cd dir1
$ echo "hello world" > 1.txt
$ git add dir1; 
$ git commit -a -m "add master branch"

创建develop分支
$ git checkout develop
$ mkdir dir2
$ echo "hello world" > 2.txt

master分支有ci
$ git checkout master
$ echo "add by branch master" >> 1.txt
$ git commit -a -m "update master branch"

merge master分支指定目录到develop分支
$ git checkout develop
$ git checkout master dir1/1.txt
  • git merge branchA的file1 到 branchB,仅需这样
$ git checkout branchB
$ git checkout branchA file1

Linux特殊字符(M-BM-)

有时候linux的命令贴到OneNote里后,再copy出来run就不行了,原因是有特殊字符。

$ cat /tmp/run.sh
echo hello

$ cat -A /tmp/run.sh
echoM-BM- hello$

这个"M-BM-"就是不可见的特殊字符,怀疑是windows的软件整的,需要要替换了就行

$ sed 's/\xc2\xa0/ /g' -i /tmp/run.sh

$ cat -A /tmp/run.sh
echo hello$

Nginx负载均衡+监控状态检测

Nginx负载均衡+监控状态检测

想用Nginx或者Tengine替代LVS,即能做七层的负载均衡,又能做监控状态检测,一旦发现后面的realserver挂了就自动剔除,恢复后自动加入服务池里,可以用Tengine的ngx_http_upstream_check_module模块。该模块在Tengine-1.4.0版本以前没有默认开启,它可以在配置编译选项的时候开启:./configure --with-http_upstream_check_module。

Nginx.conf 配置

http {
    upstream fire_server{
    ip_hash;
    server 192.168.1.1:80;
    server 192.168.1.2:80;

    check interval=3000 rise=2 fall=5 timeout=1000 type=http ;
    check_http_send "GET /status.html HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx ;
    }

    server {
        listen       80;
        server_name  localhost default;

        location / {
            proxy_pass http://fire_server;
            access_log logs/fire_server_access.log main;
            error_log logs/error.log debug;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }   
}

- 阅读剩余部分 -

理解Linux文件系统挂载参数noatime nodiratime

很多线上服务器为了提供文件系统IO性能,会在挂载文件系统的时候指定“noatime,nodiratime”参数,意味着当访问一个文件和目录的时候,access time都不会更新。但是如果未指定上面的参数,atime则会更新。那么具体差异在哪里?

未指定 noatime,nodiratime

$ touch test ; stat test ;
...
Access: 2015-04-04 00:37:23.507135507 +0800
Modify: 2015-04-04 00:37:23.507135507 +0800
Change: 2015-04-04 00:37:23.507135507 +0800

$ echo hello >> test ; stat test;
...
Access: 2015-04-04 00:37:23.507135507 +0800
Modify: 2015-04-04 00:37:38.018430637 +0800
Change: 2015-04-04 00:37:38.018430637 +0800

$ cat test ;stat test
...
Access: 2015-04-04 00:38:02.916135510 +0800
Modify: 2015-04-04 00:37:38.018430637 +0800
Change: 2015-04-04 00:37:38.018430637 +0800

可以看出未指定"noatime,nodiratime"的情况下

  1. read文件的时候会导致atime更新,不会导致mtime和ctime更新
  2. write文件只会导致mtime和ctime更新,不会导致atime更新。

指定 noatime,nodiratime

$touch test ; stat test ; 
...
Access: 2015-04-04 00:28:28.680135484 +0800
Modify: 2015-04-04 00:28:28.680135484 +0800
Change: 2015-04-04 00:28:28.680135484 +0800

$ sleep 10 ; echo hello >> test ; stat test;
...
Access: 2015-04-04 00:28:28.680135484 +0800
Modify: 2015-04-04 00:28:38.682727983 +0800
Change: 2015-04-04 00:28:38.682727983 +0800

$ cat test ;stat test
...
Access: 2015-04-04 00:28:28.680135484 +0800
Modify: 2015-04-04 00:28:38.682727983 +0800
Change: 2015-04-04 00:28:38.682727983 +0800

可以看出指定"noatime,nodiratime"的情况下

  1. read文件的时候不会导致atime、mtime、ctime改变
  2. write文件只会导致mtime和ctime更新,不会导致atime更新。

实际应用场景

在平日里经常有删除文件的需求,大概如下

删除过去N天内都未访问过的文件或者目录(删除N天前访问过的文件)

$ #注意这条命令很危险! 
$ find /home/fire/ -atime +N -exec rm -rf {} \;

假设 /home/fire 目录是一周之前创建的,那么对于这条命令有两个执行结果

$ #注意这条命令很危险! 
$ find /home/fire/ -atime +7 -exec rm -rf {} \;
  • 指定"noatime":find的时候发现 /home/fire 是7天之前创建的,立马就会删除整个目录。而且还会报错"find: /home/fire: No such file or directory",原因就是第一个rm -rf /home/fire 之后 find失败了。这种是很危险的!原因是会误删除文件。
  • 未指定"noatime":那就得看情况,如果/home/fire过去7天没有被访问过,那么就和情况一一样,直接删除。如果过去7天内,该目录有人访问过,atime肯定是7天之内,那么就会遍历下面的目录,依次按照之前逻辑。但是遍历过程会更改目录的atime。

看了上面的例子会发现find去删除目录的时候变得好复杂,而且一定要小心。所以find删除更适用于删除文件,不要删除目录。

删除N天内未被访问过的文件
$ find /home/fire/ -atime +N -type f -exec rm -f {} \;