18
五 12

发挥网卡性能到极致

当下的网卡大都已经支持多队列了。

多队列,网卡就可以把“中断”呼叫分派给不同的处理器,而不必以前那样,只有一个处理器在处理网络流量。

“多队列”需要网卡硬件以驱动程序两者配合才能发挥作用。升级内核到最新(发行版自带的),这很重要。

查看/proc/interrupts中是否包含多个eth0-,有几个就有几个队列。有几个队列,就可以同时“中断”几个CPU,相当于可以有几个“并发”处理。

irqbalance这个应用本来是好意,但是在网卡多队列的时候,这个东东还是关闭为好。然后将“中断”绑定到固定的CPU上,这样:

1. 可以提高CPU缓存的命中率(这个对速度的提高,效果很明显)。

2. 可以降低CPU互斥。

如何绑定,查看内核文档:filesystems/proc.txt、IRQ-affinity.txt。

 


18
五 12

rhel6上的chkconfig

有一点小发现,都需要记下来,不然转眼就忘。

在RHEL5的时候,还在想,我的原来对/etc/init.d/network的修改需求,该如何是好?

直接修改?这严重违背了“能不修改系统就能解决的问题,坚决不修改系统”、“不是万不得已决不修改系统”的原则。

想来,这样的“原则”和需求,是“共性”,RHEL6的chkconfig提供了/etc/chkconfig.d目录。可以使用/etc/chkconfig.d/name取代/etc/init.d/name:

chkconfig –override –add name

 

 


15
五 12

通过信号“暂停”和“继续”进程执行

信号SIGSTOP(19),可以让进程“暂停”执行,而信号SIGCONT(18)可以使暂停进程“继续”执行……

其实Ctrl-Z产生的,就是SIGSTOP信号。而fg命令,可能就是产生的SIGCONT信号。

man 7 signal 有详细描述。


15
五 12

快速切换内核

内核在2.6.13版,提供了kexec_load系统调用,RHEL的kexec-tools包提供了kexec工具,这个工具可以快速切换内核。

使用kexec切换内核的好处是,系统不必“重启”,硬件不需要POST,这样一来,速度会快不少。

另外,遇到POST过程不能自动通过的情况(需要手动按F1之类……),使用这个工具来重启系统也不错。

目前还没有发现“负作用”。


14
五 12

了解CPU

上周听了褚霸的《了解CPU》,受益匪浅。对褚霸此人的佩服,又加深一层……

他的“成功”事迹,正验证了那句技术圈子里耳熟能详的话“对做的事儿了解的越深入,才能做的越好”。

这个PPT讲得近几年、当前淘宝正在使用的主流CPU的相关技术……从CPU的结构、原理的角度来讲程序的执行效率。

很多地方没有听懂,把还能记得的大概意思记录如下(总比没有强):

第4页:多核处理器
http://baike.baidu.com/view/2219502.htm

重点:多核处理器,一般共享L3(LLC——最后一级缓存)。

第6页:一级缓存分数据缓存L1(D)和指令缓存L1(I),并且在处理器缓存中有Cache Lines概念,当下的主流CPU的Cache Lines是64字节。注意这个Cache Lines的大小,能极大地优化程序效率,比如Nginx的代码就很注重对Cache Lines的“对齐”。

第X页:在Core之是迁移进程开稍不可忽略。在Core之间迁移进程(线程),会使Core的缓存失效……。

 

更多处理器的知识见“技术手册”中的“了解CPU”一段。


11
五 12

在线修改limits

2.6.32内核,允许在不重启进程的情况下,修改进程的limits限制。

假定进程的PID是n,假定我们要修改”Max open files”,那么可以这样操作:

echo -n “Max open files=2048:2048″  > /proc/n/limits

注意:

1. echo 必须使用-n参数

2. 后面的重定向使用’>’还是’>>’都行。

 


09
五 12

网卡的工作机制

每一个网卡上都有一块FIFO存储器,对于NIC(Network Interface Controller),FIFO存储器是用来通过系统总线传送数据到系统存储器之前,缓存从LAN上接收到的数据。对与快速以太网还有一个直接内存存取(DMA:Directly Memory Access)控制器,用于提供对系统存储器的可靠访问。

驱动为网卡分配一个环形缓冲区,在一段连续的物理内存中实现。

1、 数据接收
(1) 接收来自MAC的数据包,先暂存于片内FIFO接收队列;
(2) 当接收器达到早期接收上线时就移至环形缓冲区;
(3) 待整个数据包全部从FIFO移至缓存后,将接收状态寄存器和包长度写入接收的数据包头部,并更新CBA(Current Buffer Address)寄存器的值;
(4) CMD(Command)寄存器中的BufferEmpty位和ISR(中断状态寄存器)寄存器的ROK位置1,并发出ROK的中断;
(5) ISR中断调用完成后,清除ISR(ROK)并更新CAPR(Current Address of Packet Read,指向接收缓存的已读取包的地址),完成本次接收。

2、 数据发送

(1) 将待传送的数据写入主存中一段连续的缓存空间,由OS配合驱动程序完成;
(2) 找到一个可用的描述器,并写入内容,包括该数据包的开始物理地址和传输状态字(包的大小、可传送下限、OWN位);
(3) OWN位有效,将数据从缓存移至片内FIFO队列;
(4) 当FIFO队列中的数据达到早期传送下限,NIC的传送单元就会启动,将数据顺序输出至线路;
(5) 当整个数据包都已经传至FIFO,OWN位置1;
(6) 当整个数据包都已经传至线路上, TOK寄存器置1;
(7) 当TOK(IMR)和TOK(ISR)多置1,就发出TOK中断;
(8) TOK中断调用完成以后,清除TSD状态字,完成本次传送。

可以看出,网卡需要发送/接收数据,都必须以中断的方式告诉系统,系统处理中断后做出相应操作。

网卡存在一定大小的FIFO存储器,同时还有缓冲区,缓冲区是由系统以及驱动共同分配一段连续的物理内存,所有的发送/接收的数据,都必须通过FIFO已经缓冲区,只有一包数据都发送成功后,才能继续发送下一包数据。系统维护缓冲区,只有当缓冲区有空间时才会接受上层来的数据,而网卡处理数据的速率远高于接收数据的最大速率,因此在网卡上不会存在堵塞情况。

 

参考:
http://blog.chinaunix.net/uid-25839577-id-3035405.html


09
五 12

使用sed时要注意的陷阱

注意:在RHEL6上(RHEL5没有这个问题)。

使用sed时,不要用sed去编辑软link文件,因为sed编辑文件(-i)是会生临时文件的,于是软件link文件被编辑后,就变成了文件。

假如你用sed去操作/etc/rc.local时,一个陷阱出现了……(/etc/rc.local必须是指向/etc/rc.d/rc.local才有意义)。

PS:
最终确定,是RHEL的sed版本中,新增了–follow-symlinks选项,而这个选项又不是默认值,所以容易误操作。
而在RHEL5上的sed版本,会自已回避这个问题,避免错误产生。

 

http://www.bsdmap.com/2008/04/02/%e5%85%b3%e4%ba%8esed%e7%9a%84%e5%b0%8f%e5%8f%91%e7%8e%b0/


07
五 12

Linux时钟问题

/etc/localtime应该是一个文件,在RHEL6上,更是必须如此。

RHEL6对时钟的处理与RHEL5不同。

RHEL5的系统时钟,是在系统启动时——内核初始化完,由init初始化OS环境时,由/etc/rc.d/rc.sysinit从BIOS中读取到系统的,在关机时,由/etc/rc.d/halt将系统时钟写回BIOS时钟。

而RHEL6的时钟,则是由内核初始化时,从BIOS中读取的:
/var/log/messages-20120506:May  5 07:35:16 hostname kernel: [    2.306873] rtc_cmos 00:03: setting system clock to 2012-05-04 23:34:14 UTC (1336174454)

在关机时,由/etc/rc.d/halt脚本将系统时钟写回BIOS。
由内核来读取时钟,就以为着,在设置系统时钟时,/etc/localtime文件指向的/usr/share/zoneinfo/Asia/Shanghai 还不可用,因为我们的/usr通常都是单独分区的,这个时候还没有挂载。所以导致系统时钟设置出错。

重现这个问题的时候,会发现一个怪圈,即每重启一次,时钟就会多差8个小时——因为设置时钟时/etc/localtime不可写,回写时钟是,/etc/localtime是能用的。一来一回,就差上了16个小时。

在RHEL5上,有一个硬件时钟是UTC时钟还是localtime时钟的问题。(这个问题是怎么来的?)Windows系统没有这个问题,Windows将“本地时钟”写入BIOS。因为BIOS时钟没有时区概念,所以当我们装的Windows系统时,进BIOS看到的时钟,总是准确的。

当我们安装的RHEL5时,假如我们在/etc/sysconfig/clock中,写入了UTC=true,那么,BIOS中的时钟是UTC时钟,与北京时钟差8个小时。当UTC= false时,BIOS中的时钟为本地时钟。

默认地,/etc/sysconfig/clock中,统一设置了UTC=false,即BIOS中的时钟是本地时钟。(这样做,也是因为担心一些附属硬件从BIOS中读取时钟,比如远程管理卡、RAID卡里,因了读取分析日志方便)。

而当使用RHEL6时,/etc/sysconfig/clock中,默认已经没有了UTC=、与ARC=的设置,而且/etc/rc.d/rc.sysinit中也没有了从BIOS读取时钟的命令,/etc/rc.d/halt中,将系统时钟写回BIOS的方式也不再去读取分析/etc/sysconfig/clock文件,即像Windows一样,统一使用系统本地时钟,将本地时钟写入BIOS。

Linux多选的时钟机制本来有些容易让人迷茫,而RHEL6统一了这一问题,统一地使用本地时钟。

另外,对/etc/localtime不建议使用link的原因,还有一个,就是这个文件在一些系统上是link,在一些系统是文件(在RHEL是文件),不同的管理员,有不同的习惯,很有可能在调整的时候,会破坏系统的zoneinfo文件。

时钟是个参照系

此处省略一万字……


13
四 12

关于RAID和LVM的几点新认识

1. RAID rebuild时,存储的I/O被消耗了不少,I/O性能变得很低。
2. 为了减少rebuild对生产的影响,可以选用空间比较小的盘。
3. DB应该选用RAID0+1。
4. LVM默认情况下,并不能提高I/O能力(不能将I/O并行化),但是LVM其实具备这样的能力:
建立LV(strip)
建立一个有2块物理盘的条带深度为64KB的LV
lvcreate -L 50G -i2 -I64 -n gfslv vg0
lvcreate -l 100 -i2 -nstripelv testvg /dev/sda1:0-50 /dev/sdb1:50-100

建立LV(mirror)(默认大小512KB同步)
建立1份copy
lvcreate -L 50G -m1 -n mirrorlv vg0
将Mirror的LOG放在内存里(代价是每次机器重启的时候都会执行一次同步)
lvcreate -L 12MB -m1 –corelog -n ondiskmirvol bigvg
建立LV,一份数据在sda1,一份数据在sdb1 日志在sdc1
lvcreate -L 500M -m1 -n mirrorlv vg0 /dev/sda1 /dev/sdb1 /dev/sdc1

5. RAID降级时,假如有盘故障,就会丢失数据。这个在使用软RAID时,要格外注意。使用mdadm建立RAID5后,总是处于“降级”状态,有一块盘在进行rebuild,要等rebuild完成,“降级”状态消失之后,RAID才能投入使用,否则存在数据丢失的危险,即使有“备盘”,也无法保证。