双机热备+负载均衡 线上方案
(Heartbeat+DRBD+NFS+Keepalived+Lnmp)
gotop

对于网站服务器来说,可靠性之重要不用我多说,但要想做到可靠性一般需要昂贵的设备,这里最主要是就是数据同步用的共享磁盘了,磁盘柜+磁盘一共下来是20多万,这对于追求最高性价比的双机负载热备方案来说是极其不靠谱的,尤其是中小型企业,私有企业,一般经理是不会考虑这么高的成本的。我们通常做都是四台服务器+一个磁盘柜子+千兆交换机,那么这个成本下来将近30万了,而且这个方案有个弊端就是 存储依然存在单点故障,除非使用双控制+双电源+双主板设计的磁盘柜,但这种成本实在太高。那是否有更为廉价的双机方案呢,很明显开源软件帮我们解决了成本问题!!!

用Heartbeat+DRBD+NFS+Keepalived+Lnmp等开源软件实现双机负载热备架构只需要两台服务器+一台全千兆交换机,这个成本是极其低廉的,我们做运维了就是要用技术来压榨硬件性能,用最低的成本实现最高的效能,不然天天谈论的性能优化有何用?堆叠硬件不是更好?那不是我们的目的,下面我们来看看这两台服务器的双机热备+负载均衡是如何实现并且稳定运行的。

这个方案是我给一个论坛做的,论坛15分钟在线8000人,以前放在IIS里面,并发连接6000-7000左右,我给设计的双机热备方案如下图:

图一
    注意:第三台服务器可要可不要,我这里他由于成本问题,并没有采用第三台服务器,而是一共只有两台
系统环境配置

一,硬件配置:
节点一(centosa):做主负载点,和主数据库压力负载点,必须高性能高稳定高I/O

配置如下:
CPU:双CPU( 4核+4核) 5405级别
内存:8G 组三通道 DDR3 ECC内存
硬盘:1块1TB普通硬盘+2块 300G SAS15K(15000转)硬盘
网卡:2块千兆网卡
节点二(centosb):做分担负载和备服务器,稳定第一
CPU:双CPU( 4核+4核) 5405
内存:8G 组三通道 DDR3 ECC内存
硬盘:1块1TB普通硬盘+3块 300G SAS15K(15000转)硬盘
网卡:2块千兆网卡

注意:网卡极力建议用四块,这个架构对网络I/O要求极高,我这里只有两块,没办法,机房做不到,如果你是百兆交换机,拜托,你一定要用四块网卡

二,操作系统配置

1),所有服务器的操作系统版本:
操作系统版本:CentOS5.7 64位
操作系统官方下载地址:http://isoredirect.centos.org/centos/5/isos/x86_64/
2),每台服务器的安装要求:
节点一:
分区:一共三块硬盘,不用组RAID
第一块硬盘:
系统占用一块,分区情况如下:
/boot                     200MB
/                             40GB
swap交换分区        8GB
/data                      第一块硬盘的所有剩余空间
第二块硬盘:
不要分区,留给我自己分区
第三块硬盘:
不要分区,留给我自己分区
系统安装安装规范
最小化安装,字符界面安装
去掉所有组件,只需要一个内核
节点二:
分区:一共三块硬盘,不用组RAID
第一块硬盘:
系统占用一块,分区情况如下:
/boot        500MB
/                 40GB
swap交换分区        16GB
/data        第一块硬盘的所有剩余空间
第二块硬盘:
不要分区,留给我自己分区
第三块硬盘:
不要分区,留给我自己分区
系统安装要求
最小化安装,字符界面安装
去掉所有组件,只需要一个内核
三,交换机配置:
注意:有条件最好用两台交换机,内网一台,外网一台
如果只有一台交换机,划分两个VLAN,一个外网使用,一个内网使用
四,目录规划用途
/usr/local/src/lnmp:用来存放源码工具等等
/data:用来存放所有数据和NFS以及DRBD的挂载
/data/shell:用来存放所有管理脚本
/data/mysql:用来挂载DRBD的mysql资源,以供mysql存放数据库
/data/wwwnfs:用来挂载DRBD生成的www资源,以供两个节点挂载到各个节点的/data/www目录,以供论坛等程序数据使用
/data/www:用来挂载NFS资源,用来存放论坛(网站)等程序数据
双机热备+负载均衡具体配置
一,先建立用户和目录吧:
useradd -s /sbin/nologin www
useradd -s /sbin/nologin mysql
mkdir -p /data/mysql
mkdir -p /data/www
mkdir -p /data/wwwnfs
mkdir -p /data/shell
二,架构详解
如果用LVS做均衡器拓扑图如下:
图二
如果用Nginx做均衡器拓扑图如下:
图三
我们这里用NGINX做均衡器,因此我用图三来拓扑,来讲讲这个拓扑的工作原理
内网:
1,DRBD网络存储创建出两个资源,一个mysql给mysql数据库同步用,一个www给web(论坛)数据NFS共享挂载用,虚拟出两个虚拟IP,一个是 192.168.1.100,用来连接数据库,一个是192.168.1.200,用来给节点挂载NFS
注意:NFS底下挂载了三次:DRBD挂载一次,文件系统挂载一次,客户端挂载一次
2,Heartbeat来实现DRBD的HA,同时虚拟出两个内网IP,并管理NFS,MySQL的启动和关闭
外网:
1,两个节点都用Nginx做均衡器,通过内网调度负载两个节点,实现内部均衡
2,DNS配置双IP对应一个域名的方式来实现DNS轮询,实现外网均衡
3,Keepalived使用双主(master)配置虚拟出两个虚拟IP:节点一 12.12.12.100和节点二 12.12.12.200,同时共外网访问,两个节点互为主从关系,当某个节点挂掉的时候,另外一个节点将同时是两个资源的master,同时拥有两个虚拟IP,实现资源转移
我们知道DNS的缺点就是生效慢,分配资源不合理,理论上有可能把所有的请求都发送给同一节点,导致均衡不合理导致所有资源不可用,这里我们由于有了NGINX内部负载,就不怕DNS轮询不均衡了,因为NGINX内部有严谨的调度方式,不管那台请求有多少,在内部都能实现理想的调度,这样就能把DNS负载均衡和NGINX完美结合,是硬件资源得到合理的利用,然后利用keepalive保证了每个节点的可靠性,几乎完美!

三,LNMP架构配置
两台服务器的一样配置这个我请看我发的这个帖子:http://bbs.ywlm.net/thread-2-1-1.html
注意一:这里MYSQL都不要初始化,不要启动!后面有专门的配置的
注意二:nginx所有端口都改成 8080,因为一会还要安装nginx来做均衡器并对外提供服务,所以不要用默认的80

四,安装配置NFS
兵马未动粮草先行,NFS是网站存放数据实现数据同步的基础,我们先安装上吧

1,安装:
服务器端要安装:
nfs-utils:NFS主程序
portmap:RPC主程序

客户端要安装:
nfs-utils:NFS主程序
portmap:RPC主程序

由于我们这里一共只用了两台服务器,所以,这里客户端和服务器段是同一台机器,这点要注意了

两个节点同时安装:

  1. yum -y install portmap nfs-utils

复制代码

2,配置:
生存共享目录vi /etc/exports
输入:

  1. /data/wwwnfs 192.168.1.0/24(rw,sync,anonuid=501,anongid=501)

复制代码

注意:
/data/wwwnfs:就是给两个节点挂载的目录,所有网站程序都放在这里,实现论坛程序等数据的共享(同步)
anonuid=501,anongid=501:这个表示客户端上任何用户进入到挂载目录都以uid=501和gid=501身份,我这里这个代表的是www用户

3,启动:
service portmap start
service nfs start
切忌,必须先启动portmap

chkconfig --level 0123456 nfs off
chkconfig --level 0123456 portmap on

注意:portmap服务器必须常驻,且不收heartbeat管理;而nfs这必须要用heartbeat来管理他的启动和关闭,所以这里要关闭nfs开机自动启动

同时要启动锁机制,因为同时有两个节点要使用同一份数据,所以需要有总裁,这个尤其是在NFS给mysql用的时候是必须要用的,对于论坛或网站,要看情况,如果存在对同一文件同时修改的时候必须要启动NFS锁机制,如果没有这种情况,那么建议不要启动,启动了会降低NFS的性能:

/sbin/rpc.lockd
echo "/sbin/rpc.lockd" /etc/rc.local

4,建立NFS的管理脚本
有人奇怪了,nfs用RPM安装的,应该直接用service nfs start/stop即可啊,维护还要建立脚本呢,这里由于NFS的启动关闭权要交给heartbeat处理,而默认/etc/init.d/nfs这个启动脚本在heartbeat处理的时候有问题,所以这里自己建立了一个

vi nfs
输入:

  1. #!/bin/bash
  2. NFSD=/etc/rc.d/init.d/nfs
  3. NFSDPID=`/sbin/pidof nfsd`
  4. case $1 in
  5. start)
  6. $NFSD start;
  7. ;;
  8. stop)
  9. $NFSD stop;
  10. if [ "$NFSDPID" != " " ];then
  11. for NFSPID in $NFSDPID
  12. do /bin/kill -9 $NFSPID;
  13. done
  14. fi
  15. ;;
  16. *)
  17. echo "Syntax incorrect. You need one of {start|stop }"
  18. ;;
  19. esac

复制代码

wq保存退出
chmod +x nfs

OK,NFS服务器端配置完毕。

注意如果你用的是四台服务器或者更多,把均衡器和节点分开的,那么还需要在节点也就是NFS的客户端安装:

  1. yum -y install portmap nfs-utils

复制代码

并且启动portmap
service portmap start
chkconfig --level 35 portmap on
注意,客户端必须要启动portmap,且要安装nfs-utils,但不需要启动NFS

我们这里均衡器和节点都在同一台服务器上,所以就免去了这些过程了,不过他同时是客户端,所以要建立挂载脚本
vi /data/shell/mountnfs.sh
输入:

  1. /bin/mount -t nfs -o nosuid,noexec,nodev,rw,nouser,noauto,bg,hard,nointr,rsize=32k,wsize=32k,tcp 192.168.10.200:/data/wwwnfs /data/www

复制代码

chmod +x /data/shell/mountnfs.sh
echo "/data/shell/mountnfs.sh" /etc/rc.local

在另外一台节点centosb上也这样安装

五,安装配置DRBD

1,分区
DRBD可用设备有如下:
(1)一个磁盘,或者是磁盘的某一个分区
(2)一个soft raid 设备
(3)一个LVM的逻辑卷
(4)一个EVMS(Enterprise Volume Management System,企业卷管理系统)的卷
(5)其他任何的块设备
这里我是建立在一个分区上的

查看磁盘信息:

  1. fdisk -l

复制代码

Disk /dev/sda: 1000.2 GB, 1000204886016 bytes
255 heads, 63 sectors/track, 121601 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          64      514048+  83  Linux
/dev/sda2              65        5163    40957717+  83  Linux
/dev/sda3            5164        7203    16386300   82  Linux swap / Solaris
/dev/sda4            7204      121601   918901935    5  Extended
/dev/sda5            7204      121601   918901903+  83  Linux

Disk /dev/sdb: 300.0 GB, 300069052416 bytes
255 heads, 63 sectors/track, 36481 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot      Start         End      Blocks   Id  System

Disk /dev/sdc: 300.0 GB, 300069052416 bytes
255 heads, 63 sectors/track, 36481 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot      Start         End      Blocks   Id  System

三块磁盘:
一块1TB已经分区,安装了操作系统和存放数据
另外两块没有分区,特用来给DRBD用

下面分区:
fdisk /dev/sdb
......
fdisk /dev/sdc
......

分区好后我们得到两个未挂载的分区
/dev/sdb1               1       36481   293033601   83  Linux
/dev/sdc1               1       36481   293033601   83  Linux

/dev/sdb1用于数据库
/dev/sdc1用于NFS

注意:先不要挂载

2,安装DRBD

1),下载
DRBD官方网站:http://www.linux-ha.org/DRBD
源码下载地址: http://oss.linbit.com/drbd

2),安装
DRBD有三种安装模式:
RPM包安装,直接编译进内核 或 作为一个可加载的内核模块编译。
RPM包安装内核版本必须是2.6.33或高于2.6.33,否则要先升级内核,2.6.33或高于2.6.33内核里面已经集成的有DRBD模块
uname -r可以看到内核版本,我的是

这里我用的是源码编译安装
如果内核版本低于2.6.33那么需要编译模块到内核,且先要安装kernel-devel
yum install gcc gcc-c++ make glibc flex wget kernel-devel

cd /src/local/src
wget http://oss.linbit.com/drbd/8.3/drbd-8.3.10.tar.gz
tar -zxvf drbd-8.3.10.tar.gz
cd drbd-8.3.10
./configure --prefix=/ --with-km --with-heartbeat

安装完成后会在/etc/ha.d/resource.d目录下生成
drbddisk  drbdupper这两个文件

make KDIR=/usr/src/kernels/2.6.18-194.el5-i686/
make install

注意:make KDIR=/usr/src/kernels/2.6.18-194.el5-i686/这个一定要是你当前加载的内核,如果你内核升级了,一定要去报这个的路径是当前加载的内核版本的路径哦
查看当前加载的内核版本方法是:
uname -r
或着
vi /boot/grub/menu.lst

检查是否安装妥当:

  1. ls /lib/modules/`uname -r`/kernel/drivers/block/drbd.ko

复制代码

drbd.ko

看到这个,就说明已经安装完好

加载到内核

  1. insmod /lib/modules/`uname -r`/kernel/drivers/block/drbd.ko

复制代码

检查内核是否已经加载了drbd模块
lsmod | grep drbd  
drbd    226352  2        
//有的话表示加载模块成功.

检查安装文件
find / -name drbd*

3,配置DRBD
DRBD有三种配置文件:
/etc/drbd.conf
/etc/drbd.d/global_common.conf
/etc/drbd.d/*.res

第一个配置文件:/etc/drbd.conf
vi /etc/drbd.conf

  1. # You can find an example in  /usr/share/doc/drbd.../drbd.conf.example
  2. include "drbd.d/global_common.conf";
  3. include "drbd.d/*.res";

复制代码

默认就是这个,我们不用管他,默认即可

第二个配置文件:/etc/drbd.d/global_common.conf
这个是全局配置文件,包括监听,同步速率等等极为重要的参数
vi /etc/drbd.d/global_common.conf

输入:

  1. global {
  2. #是否参加DRBD使用者统计,默认是yes
  3. usage-count no;
  4. }
  5. common {
  6. #使用协议C复制模式
  7. protocol C;
  8. handlers {
  9. #在系统出现什么故障时主服务器采取什么操作,例如挂起
  10. #local-io-error"/usr/lib/drbd/notify-io-error.sh;/usr/lib/drbd/notify-emergency-shutdown.sh; echo o > /proc/sysrq-trigger ; halt -f"
  11. }
  12. startup {
  13. wfc-timeout 0;
  14. #启动时连接其他节点的超时时间
  15. degr-wfc-timeout 120;
  16. }
  17. disk {
  18. #当磁盘有错误时,不连接
  19. on-io-error   detach;
  20. }
  21. net {
  22. timeout 60;
  23. connect-int 10;
  24. ping-int 10;
  25. max-buffers 2048;
  26. max-epoch-size 2048;
  27. #下面三行一定程度能防止脑裂问题
  28. #       after-sb-0pri discard-older-primary;
  29. #       after-sb-1pri call-pri-lost-after-sb;
  30. #       after-sb-2pri call-pri-lost-after-sb;
  31. #或下面三行也可以
  32. after-sb-0pri discard-zero-changes;
  33. after-sb-1pri discard-secondary;
  34. after-sb-2pri disconnect;
  35. }
  36. syncer {
  37. #复制时的网络速度限制
  38. rate 20M;
  39. }
  40. }

复制代码

上面是完整的配置文件,你如果理解了,就可以直接复制过去用,不会有问题

注意:rate表示同步的速率,这里的20M就是20MB,不是20Mb,所以如果你是100M交换机,那么请不要设置这么大,否则,你的交换机会被拖累的无响应的,你可以设置成8M即可,即80Mb,如果你是千M交换机,且是千兆网线和网卡,你可以设置成80M一下,但考虑到数据库,NFS共享等需要大量网络I/O的的应用,这里还是设置20M即可

第三个配置文件:/etc/drbd.d/mysql.res和/etc/drbd.d/www.res
这里面的文件在第一个配置文件里面定义了
因为我这里要建立两个资源,所以有两个,注意,两个可以写在同一个配置文件里面,我习惯用两个配置文件,我一一来看

vi /etc/drbd.d/mysql.res
定义给mysql用的资源组(注意,名字你可以自己随便取,只要在应用的时候对应上即可,不必苛求)

  1. #资源组的名称
  2. resource mysql{
  3. #定义主服务器资源
  4. on centosa{
  5. #建立块设备文件
  6. device /dev/drbd1;
  7. #要用于复制的分区
  8. disk /dev/sdb1;
  9. #定义侦听IP和端口
  10. address 192.168.1.10:7788;
  11. #meta data信息存放的方式,这里为内部存储,即和真实数据放在一起存储
  12. meta-disk internal;
  13. }
  14. #定义备服务器资源
  15. on centosb{
  16. device /dev/drbd1;
  17. disk /dev/sdb1;
  18. address 192.168.1.20:7788;
  19. meta-disk internal;
  20. }
  21. }

复制代码

vi /etc/drbd.d/www.res
定义给web用的资源组(注意,名字你可以自己随便取,只要在应用的时候对应上即可,不必苛求)

  1. #资源组的名称
  2. resource www{
  3. #定义主服务器资源
  4. on centosb{
  5. #建立块设备文件
  6. device /dev/drbd2;
  7. #要用于复制的分区
  8. disk /dev/sdc1;
  9. #定义侦听IP和端口
  10. address 192.168.1.20:7789;
  11. #meta data信息存放的方式,这里为内部存储,即和真实数据放在一起存储
  12. meta-disk internal;
  13. }
  14. #定义备服务器资源
  15. on centosa{
  16. device /dev/drbd2;
  17. disk /dev/sdc1;
  18. address 192.168.1.10:7789;
  19. meta-disk internal;
  20. }
  21. }

复制代码

注意:
1,centosa和centosb这个必须要用计算机名(不是域名),且要在内网能ping通,为此要修改下Linux下的hosts文件
vi /etc/hosts
输入:
192.168.1.10    centosa
192.168.1.20    centosb

在另外一个节点centosb上也同样这样安装

4,初始化DRBD资源
1),提升各个节点上的主
在centosa上:
drbdadm primary mysql
在centosb上:
drbdadm primary www

2),初始化DRBD分区

service drbd start
启动的时候会初始化
ps -ef | grep drbd
root      3724     1  0 20:02 ?        00:00:00 [drbd1_worker]
root      3731     1  0 20:02 ?        00:00:00 [drbd1_receiver]
root      3743     1  0 20:02 ?        00:00:00 [drbd1_asender]

我们能看到三个进程:
drbd1_worker:主进程程
drbd1_receiver:数据发送
drbd1_asender:数据接收

手动初始化命令:

  1. drbdadm create-md all

复制代码

这个命令是有极大风险的,当有数据的时候不要在使用这个命令
注意:如果无法启动的并提示无法加载DRBD,这说明在启动的时候drbd.ko无法加载,我们可以重新执行一下:

  1. insmod /lib/modules/`uname -r`/kernel/drivers/block/drbd.ko

复制代码

同时修改启动脚本:
vi /etc/init.d/drbd
在### END INIT INFO下面添加如下内容:

  1. MYLSMOD=`/sbin/lsmod | grep drbd | grep drbd | cut -d ' ' -f 1`
  2. if [ "$MYLSMOD" != "drbd" ];then
  3. /sbin/insmod /lib/modules/2.6.18-274.el5/kernel/drivers/block/drbd.ko
  4. fi

复制代码

保存在启动试试,应该就没有问题了
添加为系统自动启动:

  1. chkconfig --level 35 drbd on

复制代码

OK,第一个节点配置完成了

在另外个节点centosb上一样安装,并且配置文件一样
注意:启动会等待第二个节点起来,最好是在两个节点都配置完成的时候 两个节点一起启动!!!

5,安装后状态检查和使用
在主节点上
cat /proc/drbd

service drbd status

version: 8.3.10 (api:88/proto:86-96)
GIT-hash: 5c0b0469666682443d4785d90a2c603378f9017b build by root@centosa, 
2011-03-12 19:00:23
1: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C 
r-----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b 
oos:524265204
cs:Connected:为连接状态

在备节点上
cat /proc/drbd
version: 8.3.10 (api:88/proto:86-96)
GIT-hash: 5c0b0469666682443d4785d90a2c603378f9017b build by root@centosb, 
2011-03-12 19:01:23
1: cs:Connected ro:Secondary/Secondary ds:Inconsistent/Inconsistent C 
r-----
    ns:0 nr:0 dw:0 dr:0 al:0 bm:0 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b 
oos:524265204
cs:Connected:为连接状态

ds:表示两台节点的磁盘状态都是不一致(不符)
如果没有在各个节点上提升为主节点,那么DRBD机会法判断哪个是主节点,需要我们手动执行一下

我们在确认作为主节点的centosa上执行一下:

  1. drbdadm -- --overwrite-data-of-peer primary all

复制代码

这时,我们再看他们的状态

  1. cat /proc/drbd

复制代码

version: 8.3.10 (api:88/proto:86-96)
GIT-hash: 5c0b0469666682443d4785d90a2c603378f9017b build by root@centosa, 2011-03-12 19:00:23

1: cs:SyncSource ro:Primary/Secondary ds:UpToDate/Inconsistent C r--
---
    ns:2988560 nr:0 dw:0 dr:2996736 al:0 bm:182 lo:1 pe:8 ua:64 ap:0 
ep:1 wo:b oos:521277556
        [>....................] sync'ed:  0.6% (509060/511976)M
        finish: 4:38:27 speed: 31,180 (30,176) K/sec
主从状态,磁盘正在同步,这是第一次同步,同步的是底层信息,就像RAID1第
一次同步一样,例如确定RAID的容量(和小的硬盘的容量一样)
由此可知,必须确定了哪边是主孩子后才会开始同步
cs:SyncSource:为同步状态

单单纯查看各个节点的角色可以用下面命令
drbdadm rol mysql
drbdadm rol www

  1. cat /proc/drbd

复制代码

version: 8.3.10 (api:88/proto:86-96)
GIT-hash: 5c0b0469666682443d4785d90a2c603378f9017b build by root@centosb, 2011-03-12 19:01:23
1: cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r--
---
    ns:0 nr:3354496 dw:3354240 dr:0 al:0 bm:204 lo:3 pe:6777 ua:2 ap:0 
ep:1 wo:b 
oos:520910964
        [>....................] sync'ed:  0.7% (508700/511976)M
        finish: 1:45:08 speed: 82,564 (78,004) want: 102,400 K/sec

从主状态,磁盘正在同步
cs:SyncSource:为同步状态
第一次同步过程很慢,在同步完成以前不要重启,否则要重新同步了!

格式化分区
与软RAID、LVM等类似,要使用DRBD创建的镜像分区,不是直接使用/dev/sdb1设备,而是在配置文件中指定的/dev/drbd1等。同样的,不必等待初始化完成后才使用drbd1设备。

格式化设备:        mkfs -t ext3 -b 4096 /dev/drbd1
#这里要注意,格式化只需要在主服务器上格式一次就可以了,因为格式化也会被同步过去,尤其在有数据的时候千万不要格式化了
这里注意,我们需要在两个街道上各格式化一次,因为有两个资源组,且每个节点都有一个主节点:
centosa:mkfs -t ext3 -b 4096 /dev/drbd1
centosb:mkfs -t ext3 -b 4096 /dev/drbd2

挂载分区:
节点一centosa上:mount /dev/drbd1 /data/mysql
节点二centosb上:mount /dev/drbd2 /data/www
#需要注意,drbd1和drbd2设备只能在Primary一端被使用,下面的操作都是会报错的:
在从节点上
节点二centosb上:mount /dev/drbd1 /data/www
mount: block device /dev/drbd1 is write-protected, mounting read-only
mount: 错误的介质类型

另外,为避免误操作,当机器重启后,默认都处于Secondary状态,如要使用drbd设备,需手动把其设置为Primary。
当然,我们这里不需要操心,因为我们用heartbeat来自动设置primary和secondary

到此,DRBD部分就安装完成了。
下面的安装,二楼继续

分享到:   QQ好友和群  QQ空间  腾讯微博  腾讯朋友

收藏5  支持2  反对

正值巅峰!
 
回复

使用道具 举报

   
gotop

301

主题

431

帖子

8476

积分

版主

积分
8476
  • 发消息
沙发

  楼主 |  发表于 2011-10-12 15:23:10  |  只看该作者

本帖最后由 gotop 于 2011-10-12 15:45 编辑

六,安装配置Heartbeat

DRBD和Heartbeat都会出现脑裂情况,所以这个配置虽然简单,但维护极其艰难!

1,在主从节点上分别安装heartbeat
yum -y install heartbeat

安装完后会自动建立用户hacluster和组haclient
确保两个节点上hacluster用户的的UID和GID相同
在两台节点上分别执行:

  1. cat /etc/passwd | grep hacluster | awk -F ":" '{print $3}'cat /etc/passwd | grep hacluster | awk -F ":" '{print $4}'cat /etc/group | grep haclient | awk -F ":" '{print $3}'

复制代码

结果都相同即可

同步两台节点的时间
date
date -s "2011-10-10 11:24:00" 
clock -w

或者用npt
crontab -e
*/30 * * * * ntpdate 210.72.145.44

2,在两台节点上都修改hosts文件
vi /etc/hosts
添加
192.168.1.10         centosa
192.168.1.20         centosb
这个上面有加过

3,配置三个文件
ha.cf                监控配置文件
haresources        资源管理文件
authkeys             心跳线连接加密文件

第一个配置文件:/etc/ha.d/ha.cf

vi /etc/ha.d/ha.cf

  1. debugfile /var/log/ha-debug                             #打开错误日志报告
  2. keepalive 2                                             #两秒检测一次心跳线连接
  3. deadtime 10                                             #10 秒测试不到主服务器心跳线为有问题出现
  4. warntime 6                                              #警告时间(最好在 2 ~ 10 之间)
  5. initdead 120                                            #初始化启动时 120 秒无连接视为正常,或指定heartbeat
  6. #在启动时,需要等待120秒才去启动任何资源。
  7. udpport 694                                             #用 udp 的 694 端口连接
  8. ucast eth0 192.168.1.20                                #单播方式连接(主从都写对方的 ip 进行连接)
  9. #ucast eth1 192.168.2.20 #如果有多多个网卡可以同时在多个网卡监听, 这能有效防止脑裂
  10. #注: mcast eth0 是多播模式 bcast eth0 是广播模式
  11. #bcast eth0 eth2                                        #广播方式
  12. #serical /dev/ttyS0                                     #串行连接这用这个
  13. #baud   19200
  14. node   centosa                                           #声明主服(注意是主机名uname -n不是域名)
  15. node   centosb                                           #声明备服(注意是主机名uname -n不是域名)
  16. auto_failback on                                        #自动切换(主服恢复后可自动切换回来)这个不要开启
  17. #注: stonith baytech  /etc/ha.d/conf/stonith.baytech 控制
  18. #可编程电源控制器(挂掉的主服 ip 可能还是运行状态,
  19. #会对备服有冲突,他会自动切掉坏的主服)
  20. respawn hacluster /usr/lib64/heartbeat/ipfail           #监控ipfail进程是否挂掉,如果挂掉就重启它
  21. #ping 192.168.1.1                                        #设仲裁,双方主备都 ping 仲裁(仲裁 ip 用 DGW 最好)
  22. #ping 192.168.1.2                                        #注: ping_group            可设 1 组仲裁, ping一个网段
  23. #这里被ping的IP必须足够健壮,例如主节点无法ping通
  24. #时会问备服务器”你能通吗?”如果备服务器能通,这说明
  25. #主服务器出现故障了,备服务器应该切换资源了!

复制代码

第二个配置文件:/etc/ha.d/authkeys
vi /etc/ha.d/authkeys
输入:

  1. auth 1
  2. 1 crc

复制代码

保存,修改权限:
chmod 600 /etc/ha.d/authkeys

第三个配置文件:/etc/ha.d/haresources
vi /etc/ha.d/haresources
输入:

  1. centosa IPaddr::192.168.1.100/24/eth0 drbddisk::mysql Filesystem::/dev/drbd1::/data/drbd/mysql::ext3 mysql
  2. centosb IPaddr::192.168.1.200/24/eth0 drbddisk::www Filesystem::/dev/drbd2::/data/drbd/wwwnfs::ext3 nfs

复制代码

这个是极为关键,也是最难的地方了
注意:
drbddisk::mysql
drbddisk::www
红字部分分别为你的资源组名字,要对以上哦

注解:
IPaddr::192.168.1.100/24/eth0:用IPaddr脚本配置浮动VIP
drbddisk::data:用drbddisk脚本实现DRBD主从节点资源组的挂载和卸载
Filesystem::/dev/drbd1::/data::ext3:用Filesystem脚本实现磁盘挂载和卸载

4,建立生成资源:

cp /data/shell/nfs /etc/ha.d/resource.d/
cp /etc/init.d/mysql /etc/ha.d/resource.d/

chmod +x /etc/ha.d/resource.d/mysql
chmod +x /etc/ha.d/resource.d/nfs

OK,节点一centosa的配置完成了

在节点二centob上同意这样配置,但注意/etc/ha.d/ha.cf里面稍有不同的是ucast eth0 192.168.1.10必须监听节点一的IP

两个节点上都开启heartbeat自动启动:
chkconfig --level 35 heartbeat on

在两个节点上启动Heartbeat测试service heartbeat start

OK,到这里,两个节点的Heartbeat全部都安装完成了,三楼继续写nginx,mysql和keepalived等的配置

点评

  铁卫士
相当犀利,再次受教了   发表于 2012-3-11 19:16

  铁卫士
这里有个问题的,心跳线有单点故障哟,看我这个应该可以解决:http://bbs.ywlm.net/thread-1156-1-1.html   发表于 2012-3-11 19:16

正值巅峰!
 
点评回复 支持 反对

使用道具 举报

   
gotop

301

主题

431

帖子

8476

积分

版主

积分
8476
  • 发消息
板凳

  楼主 |  发表于 2011-10-12 15:44:46  |  只看该作者

本帖最后由 gotop 于 2011-10-12 15:47 编辑

七,nginx均衡器配置

cd /usr/local/src/lnmp

1,安装pcre(如果你在装LNMP的时候装过了,这里就不要在装了)
tar zxvf pcre-8.12.tar.gz
cd pcre-8.12/
./configure
make && make install
cd ..

2,安装nginx均衡器
tar zxvf nginx-1.0.6.tar.gz
cd nginx-1.0.6
./configure --user=www --group=www --prefix=/usr/local/lnmp/lbsnginx --with-http_stub_status_module --with-http_ssl_module
make && make install
cd ../

3,配置nginx均衡器
mkdir -p /data/logs
rm -rf  vi /usr/local/lnmp/lbsnginx/conf/nginx.conf
vi /usr/local/lnmp/lbsnginx/conf/nginx.conf
输入:

  1. user  www www;
  2. worker_processes 8;
  3. error_log  /data/logs/lbsnginx_error.log  crit;
  4. pid        /usr/local/lnmp/lbsnginx/logs/nginx.pid;
  5. worker_rlimit_nofile 65535;
  6. events
  7. {
  8. use epoll;
  9. worker_connections 65535;
  10. }
  11. http
  12. {
  13. include       mime.types;
  14. default_type  application/octet-stream;
  15. charset  gbk;
  16. server_names_hash_bucket_size 128;
  17. client_header_buffer_size 32k;
  18. large_client_header_buffers 4 32k;
  19. client_max_body_size 80m;
  20. client_body_buffer_size 512k;
  21. proxy_connect_timeout 5;
  22. proxy_read_timeout 60;
  23. proxy_send_timeout 5;
  24. proxy_buffer_size 16k;
  25. proxy_buffers 4 64k;
  26. proxy_busy_buffers_size 128k;
  27. proxy_temp_file_write_size 128k;
  28. sendfile on;
  29. tcp_nopush     on;
  30. keepalive_timeout 60;
  31. tcp_nodelay on;
  32. gzip on;
  33. gzip_min_length  1k;
  34. gzip_buffers     4 16k;
  35. gzip_http_version 1.0;
  36. gzip_comp_level 2;
  37. gzip_types       text/plain application/x-javascript text/css application/xml;
  38. gzip_vary on;
  39. #limit_zone  crawler  $binary_remote_addr  10m;
  40. upstream bbs.ywlm.net_server
  41. {
  42. server 192.168.1.10:8080 weight=3 max_fails=2 fail_timeout=30s;
  43. server 192.168.1.20:8080 weight=9 max_fails=2 fail_timeout=30s;
  44. }
  45. server
  46. {
  47. listen       80;
  48. server_name  bbs.ywlm.net;
  49. location / {
  50. root /data/www/bbs.ywlm.net;
  51. index index.php index.htm index.html;
  52. proxy_redirect off;
  53. proxy_set_header Host $host;
  54. proxy_set_header X-Real-IP $remote_addr;
  55. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  56. proxy_pass http://bbs.ywlm.net_server;
  57. }
  58. access_log  off;
  59. }
  60. server
  61. {
  62. listen       80;
  63. server_name  att.ywlm.net;
  64. index index.html index.htm index.php;
  65. root  /data/wwwroot/att.ywlm.net;
  66. #limit_conn   crawler  20;
  67. location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  68. {
  69. expires      30d;
  70. }
  71. location ~ .*\.(js|css)?$
  72. {
  73. expires      1h;
  74. }
  75. access_log  off;
  76. }
  77. }

复制代码

保存,检查配置文件是否正确:
/usr/local/lnmp/lbsnginx/sbin/nginx -t
nginx: the configuration file /usr/local/lnmp/lbsnginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/lnmp/lbsnginx/conf/nginx.conf test is successful

启动nginx:
/usr/local/lnmp/lbsnginx/sbin/nginx
echo "/usr/local/lnmp/lbsnginx/sbin/nginx" /etc/rc.local

节点一centosa上nginx均衡器安装完毕

另外一个节点centosb上同样安装即可

八,MySQL配置
这里在LNMP的时候已经安装过了,所以这里只需要进行初始化和配置即可,(下面的配置在安装LNMP的时候最好不要做!)

注意:在两个节点安装数据库的时候,都不要启动,把启动和关闭权交给heartbeat

1,建立配置文件(两个节点都要配置)
vi /etc/my.cnf
输入:

  1. [client]
  2. default-character-set = utf8
  3. port = 3306
  4. socket = /tmp/mysql.sock
  5. [mysql]
  6. no-auto-rehash
  7. [mysqld]
  8. default-character-set = utf8
  9. user = mysql
  10. port = 3306
  11. socket = /tmp/mysql.sock
  12. basedir = /usr/local/lnmp/mysql
  13. datadir = /data/mysql/data
  14. open_files_limit = 10240
  15. back_log = 600
  16. max_connections = 3000
  17. max_connect_errors = 6000
  18. table_cache = 614
  19. external-locking = FALSE
  20. max_allowed_packet = 32M
  21. sort_buffer_size = 2M
  22. join_buffer_size = 2M
  23. thread_cache_size = 300
  24. thread_concurrency = 8
  25. query_cache_size = 32M
  26. query_cache_limit = 2M
  27. query_cache_min_res_unit = 2k
  28. default-storage-engine = MyISAM
  29. default_table_type = MyISAM
  30. thread_stack = 192K
  31. transaction_isolation = READ-COMMITTED
  32. tmp_table_size = 246M
  33. max_heap_table_size = 246M
  34. long_query_time = 1
  35. #log_long_format
  36. #log-bin = /data/mysql/binlog
  37. #binlog_cache_size = 4M
  38. #binlog_format = MIXED
  39. #max_binlog_cache_size = 8M
  40. #max_binlog_size = 512M
  41. expire_logs_days = 7
  42. key_buffer_size = 256M
  43. read_buffer_size = 1M
  44. read_rnd_buffer_size = 16M
  45. bulk_insert_buffer_size = 64M
  46. myisam_sort_buffer_size = 128M
  47. myisam_max_sort_file_size = 10G
  48. myisam_max_extra_sort_file_size = 10G
  49. myisam_repair_threads = 1
  50. myisam_recover
  51. skip-name-resolve
  52. master-connect-retry = 10
  53. slave-skip-errors = 1032,1062,126,1114,1146,1048,1396
  54. server-id = 1
  55. innodb_additional_mem_pool_size = 16M
  56. innodb_buffer_pool_size = 64M
  57. innodb_data_file_path = ibdata1:1024M:autoextend
  58. innodb_file_io_threads = 4
  59. innodb_thread_concurrency = 8
  60. innodb_flush_log_at_trx_commit = 2
  61. innodb_log_buffer_size = 16M
  62. innodb_log_file_size = 128M
  63. innodb_log_files_in_group = 3
  64. innodb_max_dirty_pages_pct = 90
  65. innodb_lock_wait_timeout = 120
  66. innodb_file_per_table = 0
  67. [mysqldump]
  68. quick
  69. max_allowed_packet = 32M

复制代码

同步到centosb节点:
scp /etc/my.cnf 192.168.1.20:/etc

2,建立初始化数据:
注意,这里只需要在DRBD中的mysql资源组的主节点上初始化即可,其他的全部可以同步过去

chmod +w /usr/local/lnmp/mysql/
chown -R mysql:mysql /usr/local/lnmp/mysql/
chown -R mysql:mysql /data/mysql

初始化数据库:

  1. /usr/local/lnmp/mysql/bin/mysql_install_db --basedir=/usr/local/lnmp/mysql/ --datadir=/data/mysql/data --user=mysql

复制代码

3,设置权限
设置本地连接时root权限

  1. /usr/local/lnmp/mysql/bin/mysqladmin -u root -h 127.0.0.1 password 123456

复制代码

设置双节点访问数据库时的权限
mysql -uroot -p -h 127.0.0.1

  1. GRANT ALL PRIVILEGES ON *.* TO 'admin'@'192.168.1.%' IDENTIFIED BY '12345678';

复制代码

在论坛上就要对应着修改你连接数据库的文件了
OK,主节点的数据库按照了,启动吧
service mysql start

再次提醒,mysql配置部分不要在所有节点上做,只需要做主节点即可,其他节点已经通过DRBD同步过去了,甚至连数据库初始化都不用!!!

下楼继续配置keepalived了,就剩下最后的了

正值巅峰!
 
点评回复 支持 反对

使用道具 举报

   
gotop

301

主题

431

帖子

8476

积分

版主

积分
8476
  • 发消息
地板

  楼主 |  发表于 2011-10-12 16:00:50  |  只看该作者

本帖最后由 gotop 于 2011-10-12 16:11 编辑

九,Keepalived配置实现nginx均衡器的HA

1,安装keepalived

  1. yum -y install gcc make openssl openssl-devel wget kernel-devel
  2. mkdir -p /usr/local/src/hasoft
  3. cd /usr/local/src/hasoft
  4. wget http://www.keepalived.org/software/keepalived-1.2.2.tar.gz
  5. tar -zxvf keepalived-1.2.2.tar.gz
  6. cd keepalived-1.2.2
  7. ./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/kernels/2.6.18-238.19.1.el5-i686/

复制代码

编译完成后出现下面内容:

  1. Keepalived configuration
  2. ------------------------
  3. Keepalived version       : 1.2.2
  4. Compiler                 : gcc
  5. Compiler flags           : -g -O2 -DETHERTYPE_IPV6=0x86dd
  6. Extra Lib                : -lpopt -lssl -lcrypto
  7. Use IPVS Framework       : Yes
  8. IPVS sync daemon support : Yes
  9. IPVS use libnl           : No
  10. Use VRRP Framework       : Yes
  11. Use Debug flags          : No

复制代码

  1. make && make install

复制代码

这里注意哦,我上面是指通用的安装方法,如果你没有用到LVS可以把lvs去掉即

  1. ./configure --prefix=/usr/local/keepalived --with-kernel-dir=/usr/src/kernels/2.6.18-238.19.1.el5-i686/ --disable-lvs-syncd --disable-lvs

复制代码

但这个没有影响,就按照我的来配置吧,不过如果你要是集成了LVS,那么就不

可加这两个参数了哦

2,整理管理文件:
cp /usr/local/keepalived/sbin/keepalived /usr/sbin/
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig/
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d/

3,建立配置文件目录(注意:keepalived的配置文件默认在/etc/keepalived/目录)
mkdir -p /etc/etc/keepalived/

两台服务器(两个节点)都这样安装即可

4,配置

节点一centosa配置如下:
vi /etc/keepalived/keepalived.conf输入:

  1. global_defs
  2. {
  3. notification_email
  4. {
  5. admin@example.com
  6. admin@ywlm.net
  7. }
  8. notification_email_from admin@example.com
  9. smtp_server 127.0.0.1
  10. stmp_connect_timeout 30
  11. router_id lnmp_node1
  12. }
  13. vrrp_instance lnmpa {
  14. state MASTER
  15. interface eth0
  16. virtual_router_id 100
  17. priority 200
  18. advert_int 5
  19. track_interface {
  20. eth0
  21. eth1
  22. }
  23. authentication {
  24. auth_type PASS
  25. auth_pass 123456
  26. }
  27. virtual_ipaddress {
  28. 192.168.1.100
  29. }
  30. vrrp_instance lnmpa {
  31. state BACKUP
  32. interface eth0
  33. virtual_router_id 200
  34. priority 100
  35. advert_int 5
  36. track_interface {
  37. eth0
  38. eth1
  39. }
  40. authentication {
  41. auth_type PASS
  42. auth_pass 123456
  43. }
  44. virtual_ipaddress {
  45. 192.168.1.200
  46. }
  47. }

复制代码

节点二centosb配置如下:

  1. global_defs
  2. {
  3. notification_email
  4. {
  5. admin@example.com
  6. admin@ywlm.net
  7. }
  8. notification_email_from admin@example.com
  9. smtp_server 127.0.0.1
  10. stmp_connect_timeout 30
  11. router_id lnmp_node1
  12. }
  13. vrrp_instance lnmpa {
  14. state BACKUP
  15. interface eth0
  16. virtual_router_id 100
  17. priority 200
  18. advert_int 5
  19. track_interface {
  20. eth0
  21. eth1
  22. }
  23. authentication {
  24. auth_type PASS
  25. auth_pass 123456
  26. }
  27. virtual_ipaddress {
  28. 192.168.1.100
  29. }
  30. vrrp_instance lnmpa {
  31. state MASTER
  32. interface eth0
  33. virtual_router_id 200
  34. priority 100
  35. advert_int 5
  36. track_interface {
  37. eth0
  38. eth1
  39. }
  40. authentication {
  41. auth_type PASS
  42. auth_pass 123456
  43. }
  44. virtual_ipaddress {
  45. 192.168.1.200
  46. }
  47. }

复制代码

启动:/usr/local/keepalived/sbin/keepalived
注意,用/etc/init.d/keepalived start如果起不来,可以用/usr/local/keepalived/sbin/keepalived二进制文件直接执行启动即可

5,编写监控脚本
cd /data/shell
vi keepcheck.sh
输入:

  1. #!/bin/bash
  2. while  :
  3. do
  4. mysqlcheck=`/usr/local/lnmp/mysql/bin/mysqladmin -uroot ping 2>&1`
  5. mysqlcode=`echo $?`
  6. phpcheck=`ps -C php-fpm --no-header | wc -l`
  7. nginxcheck=`ps -C nginx --no-header | wc -l`
  8. keepalivedcheck=`ps -C keepalived --no-header | wc -l`
  9. if [ $nginxcheck -eq 0 ]|| [ $phpcheck -eq 0 ]||[ $mysqlcode -ne 0 ];then
  10. if [ $keepalivedcheck -ne 0 ];then
  11. killall -TERM keepalived
  12. else
  13. echo "keepalived is stoped"
  14. fi
  15. else
  16. if [ $keepalivedcheck -eq 0 ];then
  17. /etc/init.d/keepalived start
  18. else
  19. echo "keepalived is running"
  20. fi
  21. fi
  22. sleep 5
  23. done

复制代码

wq保存退出

  1. chmod +x /data/shell/keepcheck.sh
  2. nohup sh /data/shell/keepcheck.sh &

复制代码

设置开机自动执行脚本:

  1. echo "nohup sh /data/shell/keepcheck.sh &" >> /etc/rc.loal

复制代码

脚本在节点二centosb上也要设置

最后您设置你的DNS轮询吧,然后重启两个节点分别测试看是否成功!!!

来源: http://bbs.nanjimao.com/thread-965-1-1.html

双机热备+负载均衡(Heartbeat+DRBD+NFS+Keepalived+Lnmp)线上方案相关推荐

  1. 双机热备+负载均衡 线上方案 (Heartbeat+DRBD+NFS+Keepalived+Lnmp)

    对于网站服务器来说,可靠性之重要不用我多说,但要想做到可靠性一般需要昂贵的设备,这里最主要是就是数据同步用的共享磁盘了,磁盘柜+磁盘一共下来是20多万,这对于追求最高性价比的双机负载热备方案来说是极其 ...

  2. 防火墙双机热备+负载分担

    防火墙双机热备+负载分担实验步骤 防火墙双机热备+负载分担实验以及两者之间的区别,通过实验.配置思路加深理解 负载分担: 防火墙双击热备和负载分担的区别就在于在双机热备模式下,fw1既是pc1的网关, ...

  3. njx如何实现负载均衡_LVS + keepalived + nginx + tomcat 实现主从热备 + 负载均衡

    前言 首先声明下,由于这两天找资料,看了不少博客 ,但是出于不细心,参考者的博客地址没有记录下来,所有文中要是出现了与大家博客相同的地方,那么请大家在评论区说明并附上博客地址,我好引用进来:这里表示抱 ...

  4. Linux双机热备解决方案之Heartbeat

    拓扑图: 环境描述: 操作系统:CentOS6.3_x64 主:eth0 192.168.10.10 心跳:eth1 192.168.1.10 备:eth0 192.168.10.20 心跳:eth1 ...

  5. keepalived双机热备原理及实例部署LVS+keepalived

    keepalived简介 它是由C语言编写的路由热备软件,主要提供简单高效的负载均衡及高可用解决方案.keepalived通过VRRP协议实现高可用架构.lvs实现集群分发,keepalived实现调 ...

  6. drbd实现mysql地热备_Mysql+DRBD+Heartbeat 实现mysql高可用的双机热备(mysql+heartbeat篇)...

    *************************************部署MYSQL******************************************* yum -y insta ...

  7. Heartbeat双机热备配置

    Heartbeat双机热备配置 简介 Heartbeat 项目是 Linux-HA 工程的一个组成部分,它实现了一个高可用集群系统.心跳服务和集群通信是高可用集群的两个关键组件,在 Heartbeat ...

  8. 高可用性HA(High Availability)双机热备

    对于日益承担企事业单位核心业务的NT网络来说,数据的高可用性和系统的连续运转能力极其重要,服务器是企事业单位存放数据的重要设备,如果一旦因为服务器的故障而无法正常运转,就会造成业务停顿,导致不可挽回的 ...

  9. 华为防火墙实现双机热备配置详解

    一提到防火墙,一般都会想到企业的边界设备,是内网用户与互联网的必经之路.防火墙承载了非常多的功能,比如:安全规则.IPS.文件类型过滤.内容过滤.应用层过滤等.也正是因为防火墙如此的重要,如果防火墙一 ...

最新文章

  1. 列举web开发中,为满足高性能的架构技术实现
  2. SpringBoot项目的几种创建方式,启动、和访问
  3. TCP/IP协议学习之TCP、IP篇
  4. 五十九、Vue中的样式绑定
  5. codeforces 869C The Intriguing Obsession 组合数学,逆元
  6. 新浪病毒NMGameX_AutoRun引起全公司所有打印共享器无法使用
  7. 模版方法模式 Template Method Pattern — 穷人和富人的不同婚恋历程
  8. 读书笔记:《超越需求 敏捷思维模式下的分析》
  9. Arduino与Proteus仿真实例-74LS138译码器驱动仿真
  10. three.js加载STL格式模型(vue中使用three.js52)
  11. 微信公众号测试号申请
  12. SecureCRT快捷键大全
  13. 自定义实现IOC与DI
  14. SQL Server解决18456错误方案
  15. (一)Gluster 介绍及简单部署
  16. 幼儿交往能力培养的调查研究
  17. 【CF比赛】Educational Codeforces Round 102 (Rated for Div. 2)
  18. 如何批量调整图片亮度?
  19. 乱杀HTML知识点(小白版本)
  20. java重要代码词汇_java基础必备词汇

热门文章

  1. Python 外星人入侵游戏(一):武装飞船(下)
  2. 【Pygame小游戏】剧情流推荐:什么样的游戏剧情能获得大家的喜爱?(决战紫禁之巅 )
  3. 利用Github Pages创建Hexo博客
  4. (强烈推荐)移动端音视频从零到上手
  5. 无法安装32位版本的Office,因为在您的PC上找到了以下64位程序
  6. 2022 中国开源大会“红山开源”创新论坛成功举办
  7. 文件系统之格式化与挂载
  8. 计算机毕业设计JAVA宠物找家系统mybatis+源码+调试部署+系统+数据库+lw
  9. 【verge3D】为web3D开启陀螺仪功能
  10. JavaScript之form(表单)