服务器的优化是我们最小化安装系统时应该做的事情。其实,在做这项工作之前,我们就应该根据实际应用需求来选购Linux服务器,然后有所偏重地选择硬件,比如我们应该根据服务器的应用来确定是需要RAID5,还是单块硬盘等。
无 论是租用服务器还是托管都要面临一个问题,那就是选择服务器的硬件配置。前面也说了,选购硬件配置时要根据我们的服务器应用需求而定。因为你无法 通过一台服务器来满足所有的需求、解决所有的问题。在项目实施或网站架构之前,我们应该从以下几方面来考虑如何选购Linux服务器:
这是首先需要考虑的问题,我们通常要根据服务器的应用类型(也就是用途)来决定服务器的性能、容量和可靠性需求。下面将按照负载均衡、缓存服务器、前端服务器、应用程序服务器、数据服务器的常见基础架构来讨论。
服务器就是为了给用户提供某种服务的,所以使用这些服务的用户同样是我们必须考虑的因素。我们可以从下面几个具体的问题进行评估:
有多少注册用户?正常情况下有多少用户会同时在线访问?每天同时在线访问的最高峰值大概是多少?一般在项目实施之前,客户方面会针对这些问题给出一个大致的结果。但我们要尽量设计得比这更充分和具体。同时,我们还要对未来的用户增长做一个尽可能准确的预测和规划,因为你的服务器可能会支持越来越多的用户,所以在进行网站或系统架构时要让机器能灵活地扩展。
关 于这个问题需要从两个方面来考虑,一方面是有哪些类别的数据,包括:操作系统本身占用的空间,安装应用程序所需要的空间,应用程序所产生的数据、 数据库、日志文件、邮件数据等,如果网站是Web 2.0的,还要计算每个用户的存储空间;另一方面是从时间轴上来考虑,这些数据每天都在增长,你至少要为未来1年(我们建议2~3年)的数据增长做个准确 的测算,这就需要软件开发人员和业务人员一起来提供足够的信息了。最后可将计算出来的结果乘上1.5左右的系数,方便维护的时候做各种数据的备份和文件转 移操作。
关于这个问题就需要根据自身的业务领域来考虑相关要求了。下面举几个简单的例子,帮助你了解这些服务器对可靠性、数据完整性等方面的要求。
这 里其实只是简单地讨论了业务对服务器硬件可靠性的要求。换言之,如果你觉得业务不能承担硬盘损坏带来的停机或数据丢失风险,那么一定要选择一个合 适的RAID卡。对于冗余电源问题,道理是一样的(要全面解决这个问题,不能只考虑单个服务器的硬件,还需要结合系统架构的规划设计)。
在回答了以上问题后,接下来就可以决定下面这些具体选项了:
(1)选择什么CPU
回忆一下上面关于“服务器运行的应用”和“需要支持的用户访问量”两个方面的考虑,这将帮助我们选择合适的CPU。毫无疑问,CPU的主频越高,其性能也 就越高;两个CPU要比一个CPU来得更爽,至强肯定比酷睿更猛。但究竟怎样的CPU才是合适的呢?下面为你提供一些常见情况下的建议:
- 如果你的业务刚刚起步,预算不是很充足,建议你选择一款经典的酷睿服务器,这可以帮你节约大量成本。而且,以后可以根据业务发展的情况,随时升级到更高配置的服务器。
- 如 果你需要在一台服务器上同时运行多种应用服务,例如.Net+Exchange+SQL Server,那么一个单核至强(例如X3330)或新一代的酷睿I3/I5(双核四线程)将是最佳的选择。虽然从技术的角度来说,这不是一个好主意,但 至少能够帮你节约一大笔成本。
- 如果你的服务器要运行SQL Server、MySQL或Oracle,而且目前有几百个用户同时在线,未来还会不断增长,那么你至少应该选择安装一个双四核服务器。
- 如果需要的是Web应用服务器,双四核基本就可以满足我们的要求了。
(2)需要多大的内存
同 样,“服务器运行的应用”和“需要支持的用户访问量”两方面的考虑也将帮助我们选择合适的内存容量。相比于CPU,我认为内存(RAM)才是影响 性能的最关键因素。因为在相当多正在运行的服务器中,CPU的利用率一般都在10%~30%之间,甚至更低。但我们发现由于内存容量不够而导致服务器运行 缓慢的案例比比皆是,如果服务器不能分配足够的内存给应用程序,应用程序就需要通过硬盘接口缓慢地交换读写数据了,这将导致网站慢得令人无法接受。内存的 大小主要取决于服务器的用户数量,当然也和应用软件对内存的最低需求及内存管理机制有关,所以,最好由程序员或软件开发商给出最佳的内存配置建议。下面同 样给出了一些常见应用环境下的内存配置建议:
- 无论是Windows下的IIS还是Linux下的Apache,一般情况下Web前端服务器不需要配置特别高的内存,尤其是在集群架构中,4GB的内存就已经足够了。如果有几千个并发用户,而且他们同时运行动态脚本程序,我们才会考虑使用8GB或更高的内存。
- 对于运行Tomcat、Resin、WebLogic、Websphere或.NET的应用服务器,4GB内存应该是基准配置,更准确的数字需要根据用户数量和技术架构来确定。
- 数据库服务器的内存由数据库实例的数量、表大小、索引、用户数来决定,一般建议配置4GB以上的内存,我们在许多项目方案中使用了24GB~48GB的内存。
- 诸如Postfix、Notes、Exchange这样的邮件服务器对内存的要求并不高,1GB~2GB就可以满足了。
- 还有一些特殊的服务器,我们需要为之配置尽可能高的内存容量,包括Squid、Varnish、Memcached的缓存服务器。
- 对于一台文件服务器,1GB内存可能就足够了。
事实上,上面的数字已经足够“慷慨”,由于内存技术在不断进化,价格也在不断降低,我们才得以近乎奢侈地讨论4GB、8GB、16GB这些曾经不可想象的内存容量。然而,除了花钱购买内存来满足应用程序的“贪婪”之外,系统优化和数据库优化仍然是我们需要重视的问题。
(3)需要怎样的硬盘存储系统
硬 盘存储系统的选择和配置是整个服务器系统里最复杂的一部分,我们需要考虑硬盘的数量、容量、接口类型、转速、缓存大小,以及是否需要RAID卡、 RAID卡的型号和RAID级别等问题。甚至在一些高可靠性、高性能的应用环境中,我们还需要考虑使用怎样的外部存储系统(SAN、NAS或DAS)。下 面将服务器的硬盘RAID卡的特点归纳一下:
- 如果是用作缓存服务器,比如squid、varnish还有memcached,可以考虑用RAID0。
- 如果是运行Nginx+PHP5或tomcat、resin等应用,可以考虑用RAID1。
- 如是是内网开发服务器或存放重要代码的服务器,可以考虑用RAID5。
- 如果是运行MySQL或Oracle等数据库应用,可以考虑用固态硬盘做RAID5或RAID10。
如 果你的基础架构是多服务器环境,而且服务器之间有大量的数据交换,那么建议你为每台服务器配置两个或更多的网卡,一个用来对外提供服务,另一个用 来做内部数据交换。由于现在项目外端都置于防火墙内,所以许多时候单网卡就足够了;而像LVS+Keepalived这种只用公网地址的Linux集群架 构,有时可能仅仅需要一块网卡。目前,HP或Dell这种品牌服务器自带的网卡已经足够使用了。
另外,数据的备份也是很重要的。在实际工作中我们也发现,rsync和scp这些Liunx下的备份工具同样非常占带宽,所以,如果用scp,建议尽量用它的限速参数;而rsync则尽量选择在非业务时间段执行。
由 于目前国内的DDoS攻击还是比较普遍,建议给每个项目方案和自己的电子商务网站配备硬件防火墙,比如Juniper、Cisco或神盾等。当然 了,这个问题也是网站后期运营维护需要考虑的,这里只是想让大家有个概念性的认识。有时为了数据的安全,我会让所有的机器都用RAID5。另外就是定期巡 视机房,检查服务器的硬盘灯指向,一有异常就迅速处理。
这个问题应该在项目实施前就准备好,选择服务器时应该明确1U、2U和4U到底有多少台,应该如何安排。在小项目中这个问题可能无关紧要,但在大型项目的实施过程中,这个问题就很突出了,我们应该根据现有或额定的机架数目确定到底应该选择多少个服务器。
这 个问题无论是在替公司采购时,还是在项目实施过程中,都是重要的问题。我们的方案经常被退回,理由就是超出预算。尤其是一些小项目,预算更吃紧。 我做项目时经常面临的一种需求是客户做的是证券类资讯网站,只要求周一至周五的上午9点至下午3点网站不出问题即可,并不想做复杂的负载均衡高可用。所以 这时候,我会做成单Nginx或Haproxy,后面接两台Web应用。这种情况还好说,如果是做中大型电子商务网站,在服务器成本上的控制就尤其重要。 事实上,我们经常遇到的问题是,客户给出的成本预算有限,而我们的应用又需要更多的服务器。这时候,我们不得不选择Centos或FreeBSD下的免费 虚拟化软件,这将在后面的章节中重点讲述。
以上8个方面即是我们在采购服务器时应该注意的因素,在选择服务器的组件时要有所偏重,然后根据系统或网站架构来决定服务器的数量,尽量做到服务器资源利用的最大化。
购 买了服务器(现在主流配置都是双四核),下一步就要安装系统了。这里推荐用64位的Centos5.5,安装系统时我们要选择最小化安装(不要图 形)。大家在用服务器时要记得一个原则,系统的安装包越少越好,这样机器才会更稳定。前面已经介绍过线上服务器的分区流程,如果遇到对磁盘I/O调用频繁 的服务(例如MySQL),我们可以单独拿一个分区(如/data)出来,不要跟/装在一起,避免/分区被频繁调用,出现I/O瓶颈。至于单服务器的性能 调优,本着稳定安全的原则,尽量不要改动系统原有的配置(Centos自身的文件和内存机制就很优秀),尤其是线上环境,稳定性要放在第一位来考虑。
众知周知,服务越少,系统占用的资源也会越少,所以应关闭不需要的服务。这样做的好处是减少内存和CPU时间的占用。命令如下所示:# ntsysv下面列出需要启动的服务,未列出的服务一律关闭。
- crond
Linux下的时间计划任务服务。- irqbalance
启用irqbalance服务,既可以提升性能,又可以降低能耗。irqbalance用于优化中断分配,它会自动收集系统数据以分析使用模式,并依据系 统负载状况将工作置于Performance mode或Power-save mode状态。处于Performance mode时,irqbalance会将中断尽可能均匀地分发给各个CPU core,以充分利用CPU的多核,提升性能。处于Power-save mode时,irqbalance会将中断集中分配给第一个CPU,以保证其他空闲CPU的睡眠时间,降低能耗。现在的主流服务器都是双四核,所以这项我 建议保留。- network
- sshd
- syslog
这是Linux的日志系统,必须要启动,否则机器出现问题时会找不到原因。
再说一下两个比较特殊的服务,它们是iptables和SELinux。因为网站和系统之前均有硬件防火墙,如果没有特殊需求的话,均可选择关闭。要关闭它们可以在命令setup下操作,也可以使用命令行操作。
关 闭iptables的代码如下:service iptables stop && #chkconfig iptables off关闭SELinux的方法如下:vim /etc/selinux/config然后将文件中的selinux=""改为disabled,并重启。如果不想重启系统,使用命令 setenforce 0,此命令可以暂时关闭SELinux,重启后失效。
说明 setenforce 1将SELinux设置成为enforcing模式;setenforce 0将SELinux设置成为permissive模式。另外,在lilo或grub的启动参数中增加:selinux=0,这样也可以关闭SELinux。
这段命令会使init为你打开了6个控制台,分别可以用[ALT+F1]到[ALT+F6]进行访问。此6个控制台默认都驻留在内存中,用ps -aux这个命令就可以看到,这是6个进程,如下所示:
[root@localhost ~]# ps -aux| grep tty
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.7/FAQ
root 3219 0.0 0.0 3792 488 tty1 Ss+ Mar16 0:00 /sbin/mingetty tty1
root 3220 0.0 0.0 3792 484 tty2 Ss+ Mar16 0:00 /sbin/mingetty tty2
root 3221 0.0 0.0 3792 488 tty3 Ss+ Mar16 0:00 /sbin/mingetty tty3
root 3222 0.0 0.0 3792 488 tty4 Ss+ Mar16 0:00 /sbin/mingetty tty4
root 3224 0.0 0.0 3792 488 tty5 Ss+ Mar16 0:00 /sbin/mingetty tty5
root 3226 0.0 0.0 3792 488 tty6 Ss+ Mar16 0:00 /sbin/mingetty tty6
root 3325 0.0 0.1 90548 6264 tty7 Ss+ Mar16 0:01 /usr/bin/Xorg :0 -br -audit 0 -auth /var/gdm/:0.Xauth -nolisten tcp vt7
root 6767 0.0 0.0 68284 1564 tty8 Ss+ Mar17 0:00 /bin/bash
root 31179 0.0 0.0 63372 756 pts/2 S+ 17:03 0:00 grep tty
事实上没有必要使用这么多。应如何关闭不需要的进程呢?通常我们保留前两个控制台就可以了,把后面4个用#注释掉,并且无需重启,只需要执行init q这个命令即可,如下所示:
init q
修改history记录的命令如下所示:
# vi /etc/profile
找到histsize=1000,将其改为histsize=100(这条可根据实际情况而定)。
不重启系统就可让其生效,如下所示:加入如下一行:
*/5 * * * * ntpdate ntp.api.bz
#ntp.api.bz是一组NTP服务器集群,目前有6台服务器。这项服务是api.bz继http://sms.api.bz移动飞信免费短信发送接口之后的第二项免费API服务。
如果不准备提供打印服务,可停止默认设置为自动启动的打印服务,命令如下所示:
[root@sample ~]#/etc/rc.d/init.d/cups stop ← 停止打印服务Stopping cups: [OK] ← 停止服务成功,出现“OK”
[root@sample ~]#chkconfig cups off ← 禁止打印服务自动启动
[root@sample ~]#chkconfig -list cups ← 确认打印服务自启动设置状态
cups0:off 1:off 2:off 3:off 4:off 5:off 6:off ← 0~6都为off的状态就OK(当前打印服务自启动被禁止)
然后修改相应配置文件,停止ipv6,如下所示:
[root@sample ~]#vi /etc/modprobe.conf ← 修改相应配置文件,添加如下内容
alias net-pf-10 off
alias ipv6 off
echo "IPV6INIT=no" >> /etc/sysconfig/network-scripts/ifcfg-eth0
[root@sample ~]#shutdown -r now ← 重新启动系统,使设置生效
最后确认ipv6的功能已经被关闭,如下所示:
[root@sample ~]#ifconfig -a ← 列出全部网络接口信息
eth0 Link encap:Ethernet HWaddr 00:0C:29:B6:16:A3
inet addr:192.168.0.13 Bcast:192.168.0.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:feb6:16a3/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:84 errors:0 dropped:0 overruns:0 frame.:0
TX packets:93 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:10288 (10.0 KiB) TX bytes:9337 (9.1 KiB)
Interrupt:185 Base address:0×1400lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame.:0
TX packets:12 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:952 (952.0 b) TX bytes:952 (952.0 b)
确认ipv6的相关信息没有被列出,说明ipv6功能已经关闭。
要 调整一下Linux的最大文件打开数,否则squid在高负载时执行性能将会很低。另外,在Linux下面部署应用时,有时候会遇上 Socket/File:Can’t open so many files这样的问题,这个值也会影响服务器的最大并发数。其实Linux是有文件句柄限制的,但默认不是很高,一般是1024,生产服务器很容易就会达 到这个值,所以需要改动此值。刚开始我采用vim/etc/security/limit.conf命令,在最后一行添加如下代码:
* soft nofile 60000
* hard nofile 65535
但重启后一切都还原了。
当然了,我们也可以在Nginx的一些监控脚本里实时添加此命令行,达到重启也能生效的目的。
另外,ulimit -n命令并不能真正看到文件的最大文件打开数,大家可用如下脚本查看:一个Linux文件默认有3个时间。
- atime:对此文件的访问时间。
- ctime:此文件inode发生变化的时间。
- mtime:此文件的修改时间。
如果有多个小文件(比如Web服务器的页面上有多个小图片),通常就没有必要记录文件的访问时间了,这样可以减少写磁盘的I/O。这要如何配置呢?
首 先,修改文件系统的配置文件:vim /etc/fstab。然后,在包含大量小文件的分区中使用noatime和nodiratime这两个命 令。例如:/dev/sda5 /data/pics ext3 noatime,nodiratime 0 0这样文件被访问时就不会再产生写磁盘的I/O了。
内 核的优化跟服务器的优化一样,应本着稳定安全的原则。下面以64位的Centos5.5下的Squid服务器为例来说明,待客户端与服务器端建立 TCP/IP连接后就会关闭SOCKET,服务器端连接的端口状态也就变为TIME_WAIT了。那是不是所有执行主动关闭的SOCKET都会进入 TIME_WAIT状态呢?有没有什么情况使主动关闭的SOCKET直接进入CLOSED状态呢?答案是主动关闭的一方在发送最后一个ACK后就会进入 TIME_WAIT状态,并停留2MSL(Max Segment LifeTime)时间,这个是TCP/IP必不可少的,也就是“解决”不了的。
TCP/IP的设计者如此设计,主要原因有两个:
在Squid服务器中可输入查看当前连接统计数的命令,如下所示:
netstat -n| awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
- CLOSED:无连接是活动的或正在进行中的。
- LISTEN:服务器在等待进入呼叫。
- SYN_RECV:一个连接请求已经到达,等待确认。
- SYN_SENT:应用已经开始,打开一个连接。
- ESTABLISHED:正常数据传输状态。
- FIN_WAIT1:应用说它已经完成。
- FIN_WAIT2:另一边已同意释放。
- CLOSING:两边同时尝试关闭。
- TIME_WAIT:另一边已初始化一个释放。
- LAST_ACK:等待所有分组死掉。
也就是说,这条命令可以把当前系统的网络连接状态分类汇总。
在Linux下高并发的Squid服务器中,TCP TIME_WAIT套接字数量经常可达两三万,服务器很容易就会被拖死。不过,我们可以通过修改Linux内核参数来减少Squid服务器的TIME_WAIT套接字数量,命令如下所示:
vim /etc/sysctl.conf
然后,增加以下参数:
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_max_tw_buckets = 5000
其中:
执行以下命令使内核配置立即生效:
/sbin/sysctl -p
如果是用于Apache或Nginx等的Web服务器,或Nginx的反向代理,则只需要更改以下几项即可:
net.ipv4.tcp_syncookies=1
net.ipv4.tcp_tw_reuse=1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65000执行以下命令使内核配置立即生效: /sbin/sysctl -p如果是邮件服务器,则建议内核方案如下:net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 5000 65000
kernel.shmmax = 134217728
执行以下命令使内核配置立即生效:
/sbin/sysctl -p
当 然这些都只是最基本的更改,大家还可以根据自己的需求来更改内核的设置,同样也要本着稳定的原则,如果服务器不稳定的话,一切工作和努力都会白 费。如果以上优化仍无法满足你的要求,有可能你需要定制你的服务器内核或升级服务器硬件。至于服务的配置优化,超出了本章的内容,大家可根据自己的需求有 针对性地进行更改。
建议在安装线上的生产服务器软件包时都用源码安装,这是因为源码安装可以自行调整编译参数,最大化地定制安装结果。这里以MySQL 5线上环境的编译安装来说明之,其编译参数如下所示:
./configure -prefix=/usr/local/mysql -without-debug -without-bench -enable-thread-safe-client -enable-assembler -enable-profiling -with-mysqld-ldflags=-all-static -with-client-ldflags=-all-static -with-charset=latin1 -with-extra-charset=utf8,gbk -with-innodb -with-csv-storage-engine -with-federated-storage-engine -with-mysqld-user=mysql -without-embedded-server -with-server-suffix=-community -with-unix-socket-path=/usr/local/mysql/sock/mysql.sock && make && make install
在安装MySQL时,源码安装与rpm安装相较,其特点如下:
理论上源码静态编译方式安装效率会高一点,但到底比rpm方式高多少得看具体情况,一般在5%左右。
某 次在线上环境工作,我用yum卸载一个软件包时遇到了极其危险的情况,这里也跟大家分享一下:当时,yum remove自动卸载了许多这个软件包自身依赖的系统包,导致系统崩溃了,SSH不能登录,并且SCP及RSYNC也都不能用了,幸亏FTP命令还能用, 所以数据很快被FTP传到其他服务器上了,但系统已经彻底崩溃,只有重装了。如果是源码安装的软件包就没有这种危险,需要卸载时只需要删除软件包安装的目 录即可。
综上所述,源码安装的好处如下:
这里也简单介绍一下在Linux/Unix下安装软件的源码三部曲,在后面我们会经常看到它们的身影。
./configure
make
make install
./configure是用来检查环境变量及配置编译选项的,make是用来将源代码编译成二进制文件的,而make install则会将make编译出来的文件安装到指定位置(或默认位置)。