Keepalived+HAProxy基於ACL實現單IP多功能變數名稱負載功能

来源:https://www.cnblogs.com/yan-linux/archive/2023/03/10/17203752.html
-Advertisement-
Play Games

編譯安裝 HAProxy 新版 LTS 版本,編譯安裝 Keepalived 開啟HAProxy多線程,線程數與CPU核心數保持一致,並綁定CPU核心 因業務較多避免配置文件誤操作,需要按每業務一個配置文件並統一保存至/etc/haproxy/conf.d目錄中 基於ACL實現單IP多功能變數名稱負載功能, ...


  • 編譯安裝 HAProxy 新版 LTS 版本,編譯安裝 Keepalived
  • 開啟HAProxy多線程,線程數與CPU核心數保持一致,並綁定CPU核心
  • 因業務較多避免配置文件誤操作,需要按每業務一個配置文件並統一保存至/etc/haproxy/conf.d目錄中
  • 基於ACL實現單IP多功能變數名稱負載功能,兩個功能變數名稱的業務: www.yanlinux.org 和 www.yanlinux.edu
  • 實現MySQL主從複製
  • 對 www.yanlinux.edu 功能變數名稱基於HAProxy+Nginx+Tomcat+MySQL,並實現Jpress的JAVA應用
  • 對 www.yanlinux.org 功能變數名稱基於HAProxy+Nginx+PHP+MySQL+Redis,實現phpMyadmin的PHP應用,並實現Session會話保持統一保存到Redis

1 DNS伺服器配置

在10.0.0.7主機上搭建www.yanlinux.org(VIP:10.0.0.100)和www.yanlinux.edu(VIP:10.0.0.200)的DNS解析。

配置的關鍵:

  • 在主配置文件/etc/named.conf中要將listen-on port 53 { 127.0.0.1; }中的127.0.0.1改為localhost;還需要將allow-query { localhost; };前面加上//註釋掉,或者將其中的localhost改為any,或者在後面加上各個網段信息。
  • 各個功能變數名稱解析庫文件的許可權應改為641,屬組為named
#利用腳本自動搭建www.yanlinux.org的dns解析配置
[root@dns ~]$ cat install_dns.sh 
#!/bin/bash

DOMAIN=yanlinux.org
HOST=www
HOST_IP=10.0.0.100

CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`
. /etc/os-release

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}


install_dns () {
    if [ $ID = 'centos' -o $ID = 'rocky' ];then
	    yum install -y  bind bind-utils
	elif [ $ID = 'ubuntu' ];then
        color "不支持Ubuntu操作系統,退出!" 1
        exit
	    #apt update
	    #apt install -y  bind9 bind9-utils
	else
	    color "不支持此操作系統,退出!" 1
	    exit
	fi
    
}

config_dns () {
    sed -i -e '/listen-on/s/127.0.0.1/localhost/' -e '/allow-query/s/localhost/any/' /etc/named.conf
    cat >> 	/etc/named.rfc1912.zones <<EOF
zone "$DOMAIN" IN {
    type master;
    file  "$DOMAIN.zone";
};
EOF
   cat > /var/named/$DOMAIN.zone <<EOF
\$TTL 1D
@	IN SOA	master admin.$DOMAIN (
					1	; serial
					1D	; refresh
					1H	; retry
					1W	; expire
					3H )	; minimum
	        NS	 master
master      A    `hostname -I`         
$HOST     	A    $HOST_IP
EOF
	#修改許可權和屬組
   chmod 640 /var/named/$DOMAIN.zone
   chgrp named /var/named/$DOMAIN.zone
}

start_service () {
    systemctl enable --now named
	systemctl is-active named.service
	if [ $? -eq 0 ] ;then 
        color "DNS 服務安裝成功!" 0  
    else 
        color "DNS 服務安裝失敗!" 1
        exit 1
    fi   
}

install_dns
config_dns
start_service

[root@dns ~]$ sh install_dns.sh

#yanlinux.org.zone區域數據文件信息
[root@dns ~]$ cat /var/named/yanlinux.org.zone 
$TTL 1D
@	IN SOA	master admin.yanlinux.org (
					1	; serial
					1D	; refresh
					1H	; retry
					1W	; expire
					3H )	; minimum
	        NS	 master
master      A    10.0.0.7          
www     	A    10.0.0.100

#然後拷貝yanlinux.org.zone區域子配置文件創建yanlinux.edu.zone區域子配置文件.若是自己重新創建yanlinux.edu.zone子配置文件,創建完以後需要將子配置文件的文件許可權改為640以及屬組改為named
[root@dns ~]$ cd /var/named
[root@dns named]$ cp -a yanlinux.org.zone yanlinux.edu.zone
#修改yanlinux.edu對應的信息
[root@dns named]$ vi yanlinux.edu.zone
$TTL 1D
@	IN SOA	master admin.yanlinux.edu (
					1	; serial
					1D	; refresh
					1H	; retry
					1W	; expire
					3H )	; minimum
	        NS	 master
master      A    10.0.0.7
www     	A    10.0.0.200

#兩個功能變數名稱對應的子配置文件已經創建好,然後在/etc/named.rfc1912.zones中添加區域子配置文件的信息
[root@dns ~]$ vi /etc/named.rfc1912.zones
......
#添加一下信息
zone "yanlinux.org" IN {
    type master;
    file  "yanlinux.org.zone";
};
zone "yanlinux.edu" IN {
    type master;
    file  "yanlinux.edu.zone";
};

#重新載入配置信息
[root@dns ~]$ rndc reload
server reload successful


[root@dns ~]$ dig www.yanlinux.org

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.yanlinux.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56759
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; MBZ: 0x0005, udp: 4096
;; QUESTION SECTION:
;www.yanlinux.org.		IN	A

;; ANSWER SECTION:
www.yanlinux.org.	5	IN	A	10.0.0.100

;; AUTHORITY SECTION:
yanlinux.org.		5	IN	NS	master.yanlinux.org.

;; ADDITIONAL SECTION:
master.yanlinux.org.	5	IN	A	10.0.0.7

;; Query time: 0 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Wed Mar 08 21:48:00 CST 2023
;; MSG SIZE  rcvd: 98

[root@dns ~]$ dig www.yanlinux.edu

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.yanlinux.edu
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19598
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; MBZ: 0x0005, udp: 4096
;; QUESTION SECTION:
;www.yanlinux.edu.		IN	A

;; ANSWER SECTION:
www.yanlinux.edu.	5	IN	A	10.0.0.200

;; AUTHORITY SECTION:
yanlinux.edu.		5	IN	NS	master.yanlinux.edu.

;; ADDITIONAL SECTION:
master.yanlinux.edu.	5	IN	A	10.0.0.7

;; Query time: 0 msec
;; SERVER: 10.0.0.2#53(10.0.0.2)
;; WHEN: Wed Mar 08 21:48:06 CST 2023
;; MSG SIZE  rcvd: 98

2 客戶端配置

在10.0.0.17主機上,設置DNS伺服器的IP作為其DNS,做這一步之前一定要在搭建DNS伺服器時,做好上面提到的第一個關鍵點,不然客戶端不能正確解析到功能變數名稱

[root@internet ~]$ cat /etc/sysconfig/network-scripts/ifcfg-eth0 
BOOTPROTO="static"
NAME="eth0"
DEVICE="eth0"
IPADDR=10.0.0.17
PREFIX=24
GATEWAY=10.0.0.2
DNS1=10.0.0.7  #改成DNS伺服器的IP
#DNS2=114.114.114.114
ONBOOT="yes"

#重啟網路服務
[root@internet ~]$ systemctl restart network
[root@internet network-scripts]$ cat /etc/resolv.conf 
# Generated by NetworkManager
nameserver 10.0.0.7

#測試解析
[root@internet ~]$ host www.baidu.com
www.baidu.com is an alias for www.a.shifen.com.
www.a.shifen.com has address 36.152.44.95
www.a.shifen.com has address 36.152.44.96

[root@internet ~]$ dig www.yanlinux.org

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.yanlinux.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19011
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.yanlinux.org.		IN	A

;; ANSWER SECTION:
www.yanlinux.org.	86400	IN	A	10.0.0.100

;; AUTHORITY SECTION:
yanlinux.org.		86400	IN	NS	master.yanlinux.org.

;; ADDITIONAL SECTION:
master.yanlinux.org.	86400	IN	A	10.0.0.7

;; Query time: 0 msec
;; SERVER: 10.0.0.7#53(10.0.0.7)
;; WHEN: Thu Mar 09 10:40:06 CST 2023
;; MSG SIZE  rcvd: 98

[root@internet ~]$ dig www.yanlinux.edu

; <<>> DiG 9.11.4-P2-RedHat-9.11.4-26.P2.el7 <<>> www.yanlinux.edu
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64928
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;www.yanlinux.edu.		IN	A

;; ANSWER SECTION:
www.yanlinux.edu.	86400	IN	A	10.0.0.200

;; AUTHORITY SECTION:
yanlinux.edu.		86400	IN	NS	master.yanlinux.edu.

;; ADDITIONAL SECTION:
master.yanlinux.edu.	86400	IN	A	10.0.0.7

;; Query time: 0 msec
;; SERVER: 10.0.0.7#53(10.0.0.7)
;; WHEN: Thu Mar 09 10:40:11 CST 2023
;; MSG SIZE  rcvd: 98

3 部署NFS主備服務

  1. 搭建主NFS伺服器
[root@NFS ~]$ yum -y install nfs-utils
[root@NFS ~]$ systemctl enable --now nfs-server.service

#創建用於傳輸的用戶
[root@NFS ~]$ groupadd -g 666 www 
[root@NFS ~]$ useradd -u 666 www -g 666

#創建NFS共用文件夾
[root@NFS ~]$ mkdir /data/www -p
[root@NFS ~]$ chown -R www. /data/www/

[root@NFS ~]$ mkdir /data/web2
[root@NFS ~]$ chown -R www.www /data/web2/

#添加共用配置
[root@NFS ~]$ vi /etc/exports
/data/www *(rw,all_squash,anonuid=666,anongid=666) #具有讀寫許可權,所有遠程用戶映射為666對應的用戶
/data/web2 *(rw,all_squash,anonuid=666,anongid=666)

#重啟
[root@NFS ~]$ systemctl restart nfs-server.service
[root@NFS ~]$ showmount -e 10.0.0.68
Export list for 10.0.0.68:
/data/web2 *
/data/www  *


#下載sersync,實現數據實時備份同步到NFS備份伺服器
#下載sersync,解壓,設置PATH變數
[root@NFS ~]$ wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@NFS ~]$ tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@NFS ~]$ cp -a GNU-Linux-x86/ /usr/local/sersync
[root@NFS ~]$ echo "PATH=/usr/local/sersync:$PATH" > /etc/profile.d/sersync.sh
[root@NFS ~]$ source /etc/profile.d/sersync.sh

#生成驗證文件
[root@NFS ~]$ echo lgq123456 > /etc/rsync.pas
[root@NFS ~]$ chmod 600 /etc/rsync.pas

#備份sersync配置文件,修改配置文件
[root@NFS ~]$ cp -a /usr/local/sersync/confxml.xml{,.bak}
##web1(可道雲)共用業務配置
[root@NFS ~]$ vi /usr/local/sersync/confxml.xml
1 <?xml version="1.0" encoding="ISO-8859-1"?>
  2 <head version="2.5">
  3     <host hostip="localhost" port="8008"></host>
  4     <debug start="false"/>
  5     <fileSystem xfs="false"/>
  6     <filter start="false">
  7     <exclude expression="(.*)\.svn"></exclude>
  8     <exclude expression="(.*)\.gz"></exclude>
  9     <exclude expression="^info/*"></exclude>
 10     <exclude expression="^static/*"></exclude>
 11     </filter>
 12     <inotify>
 13     <delete start="true"/>
 14     <createFolder start="true"/>
 15     <createFile start="false"/>
 16     <closeWrite start="true"/>
 17     <moveFrom start="true"/>
 18     <moveTo start="true"/>
 19     <attrib start="true"/> ##修改此行為true,文件屬性變化後也會同步
 20     <modify start="false"/>
 21     </inotify>
 22 
 23     <sersync>
 24     <localpath watch="/data/www"> ##修改此行,需要同步的源目錄
 25         <remote ip="10.0.0.48" name="backup"/> #修改此行,指定備份伺服器地址和rsync daemon的模塊名,開啟了ssh start,此時name為遠程的shell方式運行時的目標目錄
 26         <!--<remote ip="192.168.8.39" name="tongbu"/>-->
 27         <!--<remote ip="192.168.8.40" name="tongbu"/>-->
 28     </localpath>
 29     <rsync>
 30         <commonParams params="-artuz"/>
 31         <auth start="true" users="rsyncuser" passwordfile="/etc/rsync.pas"/> #修改此行為true,指定備份伺服器的rsync配置的用戶和密碼
 ......
 
 #以後臺方式執行同步
 [root@NFS ~]$ sersync2 -dro /usr/local/sersync/confxml.xml
 
 ##web2(jpress)業務共用配置
 [root@NFS ~]$ cd /usr/local/sersync/
 root@NFS sersync]$ cp confxml.xml jpress.xml
 ###相較於web1只需修改下麵標記的兩處
 [root@NFS sersync]$ vi jpress.xml
 <?xml version="1.0" encoding="ISO-8859-1"?>
  2 <head version="2.5">
  3     <host hostip="localhost" port="8008"></host>
  4     <debug start="false"/>
  5     <fileSystem xfs="false"/>
  6     <filter start="false">
  7     <exclude expression="(.*)\.svn"></exclude>
  8     <exclude expression="(.*)\.gz"></exclude>
  9     <exclude expression="^info/*"></exclude>
 10     <exclude expression="^static/*"></exclude>
 11     </filter>
 12     <inotify>
 13     <delete start="true"/>
 14     <createFolder start="true"/>
 15     <createFile start="false"/>
 16     <closeWrite start="true"/>
 17     <moveFrom start="true"/>
 18     <moveTo start="true"/>
 19     <attrib start="true"/>
 20     <modify start="false"/>
 21     </inotify>
 22 
 23     <sersync>
 24     <localpath watch="/data/web2">  #只需要將web1中的這個共用目錄改成web2的
 25         <remote ip="10.0.0.78" name="web2-backup"/> #這個是備份伺服器中定義對應web2的rsync daemon的模塊名
 26         <!--<remote ip="192.168.8.39" name="tongbu"/>-->
 27         <!--<remote ip="192.168.8.40" name="tongbu"/>-->
 28     </localpath>
 29     <rsync>
 30         <commonParams params="-artuz"/>
 31         <auth start="true" users="rsyncuser" passwordfile="/etc/rsync.pas"/>
 32         <userDefinedPort start="false" port="874"/><!-- port=874 -->
 33         <timeout start="false" time="100"/><!-- timeout=100 -->
 34         <ssh start="false"/>
 35     </rsync>
 #後臺獨立運行web2對應服務
 [root@NFS sersync]$ sersync2 -dro /usr/local/sersync/jpress.xml
 
 
 #為了防止伺服器重啟後手動執行的服務斷開,將執行命令寫進文件中,隨開機啟動
 [root@NFS ~]$ echo -e "/usr/local/sersync/sersync2 -dro /usr/local/sersync/confxml.xml &> /dev/null\n/usr/local/sersync/sersync2 -dro /usr/local/sersync/jpress.xml &> /dev/null" > /etc/profile.d/sersync2.sh
 [root@NFS ~]$ chmod +x /etc/profile.d/sersync2.sh
  1. 部署nfs備份伺服器
#在10.0.0.78 NFS備份伺服器以獨立服務方式運行rsync並實現驗證功能
[root@NFS-bak ~]$ yum -y install rsync-daemon

#創建備份目錄
[root@NFS-bak ~]$ mkdir /data/backup -p
[root@NFS-bak ~]$ mkdir /data/web2-backup

#修改配置文件,添加以下信息
[root@NFS-bak ~]$ vi /etc/rsyncd.conf
uid = www    #指定以哪個用戶來訪問共用目錄,將之指定為生成的文件所有者,預設是nobody
gid = www
max connections = 0
ignore errors
exclude = lost+found/
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
reverse lookup = no

[backup]  #每個模塊名對應一個不同的path目錄,如果同名後面模塊生效
path = /data/backup/
comment = backup dir
read only = no   #預設是yes,即只讀
auth users = rsyncuser   #預設anonymous可以訪問rsync伺服器,主伺服器中指定的用戶
secrets file = /etc/rsync.pas

[web2-backup]
path = /data/web2-backup/
comment = backup dir
read only = no
auth users = rsyncuser
secrets file = /etc/rsync.pas


#創建驗證文件
[root@NFS-bak ~]$ echo "rsyncuser:lgq123456" > /etc/rsync.pas

#創建傳輸用戶
[root@NFS-bak ~]$ chmod 600 /etc/rsync.pas
[root@NFS-bak ~]$ groupadd -g 666 www
[root@NFS-bak ~]$ useradd -u 666 www -g 666
[root@NFS-bak ~]$ chown www.www /data/backup/ -R
[root@NFS-bak ~]$ chown -R www.www /data/web2-backup/

#重載配置
[root@NFS-bak ~]$ rsync --daemon 

#放進文件中,隨主機開啟自啟動
[root@NFS-bak ~]$ echo "rsync --daemon" > /etc/profile.d/rsync.sh
[root@NFS-bak ~]$ chmod +x /etc/profile.d/rsync.sh
  1. 測試是否主備同步數據
#在NFS主伺服器上共用目錄創建一個test.txt文件,查看備份伺服器上是否同步
[root@NFS ~]$ cd /data/www/
[root@NFS www]$ touch test.txt
[root@NFS www]$ ll
total 0
-rw-r--r-- 1 root root 0 Mar  9 22:23 test.txt

[root@NFS-bak ~]$ ll /data/backup/
total 0
-rw-r--r-- 1 www www 0 Mar  9 22:23 test.txt

4 在10.0.0.48和10.0.0.58主機上搭建MySQL主從節點

  • 主節點:10.0.0.48
  • 從節點:10.0.0.58
  1. 搭建主節點
#安裝mysql
[root@mysql-master ~]$ yum -y install mysql-server

#創建二進位日誌存放路徑,併在配置文件中指定路徑以及日子文件的首碼
[root@mysql-master ~]$ mkdir /data/binlog
[root@mysql-master ~]$ chown mysql. /data/binlog/

#設置配置文件,並啟動服務
[root@mysql-master ~]$ cat /etc/my.cnf 
[mysqld]
server-id=48 
log_bin=/data/binlog/mysql-bin

[root@mysql-master ~]$ systemctl enable --now mysqld

#創建複製用戶以及授權
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "create user 'repluser'@'10.0.0.%' identified by 'lgq123456';"
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "grant replication slave on *.* to 'repluser'@'10.0.0.%';"

#創建kodbox對應資料庫以及賬號
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "create database kodbox;"
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "create user kodbox@'10.0.0.%' identified by 'lgq123456';"
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "grant all on kodbox.* to  kodbox@'10.0.0.%';"

#創建web2業務對應的資料庫和用戶
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "create database jpress;"
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "create user jpress@'10.0.0.%' identified by '123456';"
[root@mysql-master ~]$ mysql -uroot -plgq123456 -e "grant all on jpress.* to jpress@'10.0.0.%';"


#進行完全備份
[root@mysql-master ~]$ mysqldump -uroot -plgq123456 -A -F --single-transaction --master-data=1 > full_backup.sql

#拷貝備份數據到從節點
[root@mysql-master ~]$ scp full_backup.sql 10.0.0.58:
  1. 搭建從節點
#安裝
[root@mysql-slave ~]$ yum -y install mysql-server
#修改配置文件,並啟動
[root@mysql-slave ~]$ vi /etc/my.cnf
#添加下麵信息
[mysqld]
server-id=58
read-only

[root@mysql-slave ~]$ systemctl enable --now mysqld

#修改備份文件,在change master to中添加主節點信息
[root@mysql-slave ~]$ vi full_backup.sql
......
CHANGE MASTER TO 
    MASTER_HOST='10.0.0.48',  		#添上主節點ip地址
    MASTER_USER='repluser',			#添上在主節點創建的賬號
    MASTER_PASSWORD='lgq123456',	#添上賬號密碼
    MASTER_PORT=3306,				#添上埠號
    MASTER_LOG_FILE='mysql-bin.000003', 
    MASTER_LOG_POS=157;
......

#還原備份
###暫時關閉二進位日誌
[root@mysql-slave ~]$ mysql
mysql> set sql_log_bin=0;
###還原
mysql> source /root/full_backup.sql;
##開啟主從節點的鏈接線程
mysql> start slave;
##查看狀態
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for source to send event
                  Master_Host: 10.0.0.48
                  Master_User: repluser
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 157
               Relay_Log_File: mysql-slave-relay-bin.000002
                Relay_Log_Pos: 326
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 157
              Relay_Log_Space: 542
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 48
                  Master_UUID: bdcb41ce-be61-11ed-808a-000c2924e25d
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
       Master_public_key_path: 
        Get_master_public_key: 0
            Network_Namespace: 
1 row in set, 1 warning (0.01 sec)
  1. 測試主從是否同步
#在主節點上創建一個測試資料庫
mysql> create database t1;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kodbox             |
| mysql              |
| performance_schema |
| sys                |
| t1                 |
+--------------------+
6 rows in set (0.00 sec)

#在從節點查看是否存在
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| kodbox             |
| mysql              |
| performance_schema |
| sys                |
| t1                 |
+--------------------+
6 rows in set (0.01 sec)
##說明主從複製已經可以同步了

5 在10.0.0.88主機上部署redis

#安裝redis
[root@redis ~]$ yum -y install redis
#修改配置文件
[root@redis ~]$ vi /etc/redis.conf 
bind 0.0.0.0 #將此行的127.0.0.1改為0.0.0.0,實現遠程訪問
[root@redis ~]$ systemctl enable --now redis

6 搭建 www.yanlinux.org web1業務(可道雲業務)

6.1 在10.0.0.28上搭建nginx和php-fpm

# 1.利用腳本一鍵編譯安裝nginx
[root@web1 ~]$ cat install_nginx.sh 
#!/bin/bash

OS_TYPE=`awk -F'[ "]' '/^NAME/{print $2}' /etc/os-release`
OS_VERSION=`awk -F'[".]' '/^VERSION_ID/{print $2}' /etc/os-release`
CPU=`lscpu |awk '/^CPU\(s\)/{print $2}'`
SRC_DIR=/usr/local/src
read -p "$(echo -e '\033[1;32m請輸入下載的版本號:\033[0m')" NUM
NGINX_FILE=nginx-${NUM}
NGINX_INSTALL_DIR=/apps/nginx

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "
    elif [ $2 = "failure" -o $2 = "1"  ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

#下載源碼
wget_package(){
    [ -e ${NGINX_INSTALL_DIR} ] && { color "nginx 已安裝,請卸載後再安裝" 1; exit; }
    cd ${SRC_DIR}
    if [ -e ${NGINX_FILE}.tar.gz ];then
        color "源碼包已經準備好" 0
    else
        color "開始下載源碼包" 0
        wget http://nginx.org/download/${NGINX_FILE}.tar.gz
        [ $? -ne 0 ] && { color "下載 ${NGINX_FILE}.tar.gz文件失敗" 1; exit; }
    fi
}

#編譯安裝
install_nginx(){
    color "開始安裝nginx" 0
    if id nginx &> /dev/null;then
        color "nginx用戶已經存在" 1
    else
        useradd -s /sbin/nologin -r nginx
        color "nginx用戶賬號創建完成" 0
    fi

    color "開始安裝nginx依賴包" 0
    if [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '7' ];then
        yum -y install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Centos" -a ${OS_VERSION} == '8' ];then
        yum -y install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Rocky" ];then
        yum -y install make gcc libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
    elif [ $OS_TYPE == "Ubuntu" ];then
        apt update
        apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev 
    else
        color '不支持此系統!'  1
        exit
    fi

    #開始編譯安裝
    color "開始編譯安裝nginx" 0
    cd $SRC_DIR
    tar xf ${NGINX_FILE}.tar.gz
    cd ${SRC_DIR}/${NGINX_FILE}
    ./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
    make -j ${CPU} && make install
    [ $? -eq 0 ] && color "nginx 編譯安裝成功" 0 ||  { color "nginx 編譯安裝失敗,退出!" 1 ;exit; }
    ln -s ${NGINX_INSTALL_DIR}/sbin/nginx /usr/sbin/ &> /dev/null

    #創建service文件
    cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true                                                                                        
LimitNOFILE=100000

[Install]
WantedBy=multi-user.target
EOF

    #啟動服務
    systemctl enable --now nginx &> /dev/null
    systemctl is-active nginx &> /dev/null ||  { color "nginx 啟動失敗,退出!" 1 ; exit; }
    color "nginx 安裝完成" 0

}

wget_package
install_nginx

##執行腳本安裝nginx
[root@web1 ~]$ sh install_nginx.sh
[root@web1 ~]$ ss -ntl
State      Recv-Q      Send-Q           Local Address:Port           Peer Address:Port     Process     
LISTEN     0           128                    0.0.0.0:80                  0.0.0.0:*


# 2.安裝配置php-fpm
[root@web1 ~]$ yum -y install php-fpm 
##安裝php-mysql 以及php-redis所依賴的包
[root@web1 ~]$ php-mysqlnd php-json php-cli php-devel

##下載php-redis
[root@web1 ~]$ wget https://pecl.php.net/get/redis-5.3.7.tgz -P /usr/local/src/
[root@web1 ~]$ cd /usr/local/src/
[root@web1 src]$ tar xf redis-5.3.7.tgz 
[root@web1 src]$ cd redis-5.3.7/
[root@web1 redis-5.3.7]$ phpize 
Configuring for:
PHP Api Version:         20170718
Zend Module Api No:      20170718
Zend Extension Api No:   320170718
[root@web1 redis-5.3.7]$ ./configure
[root@web1 redis-5.3.7]$ make && make install

##創建php支持redis擴展的配置文件
[root@web1 redis-5.3.7]$ vi /etc/php.d/31-redis.ini
extension=redis #加入此行

[root@web1 redis-5.3.7]$ cd

#修改php上傳限制配置
[root@web1 ~]$ vi /etc/php.ini
post_max_size = 200M 		#修改為200M
upload_max_filesize = 200M 	#改為200M,實現大文件上傳

#修改配置文件
[root@web1 ~]$ vi /etc/php-fpm.d/www.conf
user = nginx 					#修改為nginx
group = nginx 					#修改為nginx
;listen = /run/php-fpm/www.sock #註釋此行
listen = 127.0.0.1:9000 		#添加此行,監控本機的9000埠
pm.status_path = /fpm_status 	#取消此行的註釋,並改為fpm_status,防止與nginx服務的status衝突
ping.path = /ping 				#取消此行的註釋
ping.response = pong 			#取消此行的註釋

##啟動服務
[root@web1 ~]$ systemctl enable --now php-fpm


# 3.配置nginx虛擬主機配置文件
##為了方便管理不同的業務,nginx支持子配置文件
##創建子配置文件目錄
[root@web1 ~]$ mkdir /apps/nginx/conf/conf.d
[root@web1 ~]$ vi /apps/nginx/conf/nginx.conf
	include /apps/nginx/conf/conf.d/*.conf; #在http語句塊最後一行添加上這一行
##創建業務配置文件
[root@web1 ~]$ cat /apps/nginx/conf/conf.d/www.yanlinux.org.conf
server {
    listen 80;
    server_name www.yanlinux.org;
    client_max_body_size 100M;
    server_tokens off;
    location / {
        root /data/kodbox/; 
        index index.php index.html index.htm;
    }
    location ~ \.php$ {
        root           /data/kodbox/;
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
        fastcgi_hide_header X-Powered-By;
    }
    location ~ ^/(ping|fpm_status)$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}


# 4.重啟服務
[root@web1 ~]$ systemctl restart nginx.service php-fpm.service

查看狀態php狀態頁,測試服務搭建成功

6.2 部署kodbox

##安裝可道雲(kodbox)所需的依賴包
[root@web1 ~]$ yum -y install php-mbstring php-xml php-gd

#下載源碼包
[root@web1 ~]$ wget https://static.kodcloud.com/update/download/kodbox.1.35.zip

[root@web1 ~]$ unzip kodbox.1.35.zip -d /data/kodbox

[root@web1 ~]$ chown -R nginx.nginx /data/kodbox/

6.3 掛載NFS伺服器,實現網站數據遠程備份

#安裝nfs-utils搭建掛載NFS
[root@web1 ~]$ yum -y install nfs-utils
[root@web1 ~]$ showmount -e 10.0.0.68
Export list for 10.0.0.68:
/data/web2 *
/data/www *

#實現永久掛載,添加以下掛載信息,利用可道雲上傳的數據都會存放在/data/kodbox/data/files目錄下,所以講這個目錄掛載nfs
[root@web1 ~]$ vi /etc/fstab
10.0.0.68:/data/www     /data/kodbox/data/files nfs     _netdev         0 0
[root@web1 ~]$ mount -a
[root@web1 ~]$ df -h|grep data
10.0.0.68:/data/www   70G  2.3G   68G   4% /data/kodbox/data/files

往可道雲上上傳文件MyHotkeyScript.ahk,測試NFS主備服務是否都可以得到數據

#查看web1伺服器上是否上傳了數據
[root@web1 ~]$ ll /data/kodbox/data/files/202303/09_079920df/
total 4
-rwxrwxrwx 1 666 666 1491 Mar  9 22:51 MyHotkeyScript.ahk

#在NFS主伺服器上查看
[root@NFS ~]$ ll /data/www/202303/09_079920df/
total 4
-rwxrwxrwx 1 www www 1491 Mar  9 22:51 MyHotkeyScript.ahk

#在NFS備份伺服器上查看
[root@NFS-bak ~]$ ll /data/backup/202303/09_079920df/
total 4
-rwxrwxrwx 1 www www 1491 Mar  9 22:51 MyHotkeyScript.ahk

7 部署www.yanlinux.edu web2業務(JPress)

7.1 在10.0.0.38主機上搭建tomcat

#利用腳本一鍵安裝jdk以及tomcat
[root@web2 ~]$ cat install_tomcat_jdk.sh
#!/bin/bash
DIR=`pwd`
read -p "$(echo -e '\033[1;32m請輸入JDK版本號:\033[0m')" JDK_VERSION
read -p "$(echo -e '\033[1;32m請輸入Tomcat版本號:\033[0m')" TOMCAT_VERSION
JDK_FILE="jdk-${JDK_VERSION}-linux-x64.tar.gz"
TOMCAT_FILE="apache-tomcat-${TOMCAT_VERSION}.tar.gz"
INSTALL_DIR="/usr/local"

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$2" && $MOVE_TO_COL
    echo -n "["
    if [ $1 = "success" -o $1 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "
    elif [ $1 = "failure" -o $1 = "1"  ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

install_jdk(){
    if ! [ -f "${DIR}/${JDK_FILE}" ];then
        color 1 "${JDK_FILE}不存在,請去官網下載"
        exit;
    elif [ -f ${INSTALL_DIR}/jdk ];then
        color 1 "JDK已經安裝"
        exit;
    else
        [ -d "${INSTALL_DIR}" ] || mkdir -pv ${INSTALL_DIR}
    fi
    tar xf ${DIR}/${JDK_FILE} -C ${INSTALL_DIR}
    cd ${INSTALL_DIR} && ln -s jdk* jdk

    cat > /etc/profile.d/jdk.sh <<EOF
export JAVA_HOME=${INSTALL_DIR}/jdk
#export JRE_HOME=\$JAVA_HOME/jre
#export CLASSPATH=.:\$JAVA_HOME/lib/:\$JRE_HOME/lib/
export PATH=\$PATH:\$JAVA_HOME/bin
EOF
    . /etc/profile.d/jdk.sh
    java -version && color 0 "JDK安裝完成" || { color 1 "JDK安裝失敗"; exit; }
}

install_tomcat(){
    if ! [ -f "${DIR}/${TOMCAT_FILE}" ];then
        color 1 "${TOMCAT_FILE}不存在,請去官網下載"
        exit;
    elif [ -f ${INSTALL_DIR}/tomcat ];then
        color 1 "tomcat已經安裝"
        exit;
    else
        [ -d "${INSTALL_DIR}" ] || mkdir -pv ${INSTALL_DIR}
    fi
    
    tar xf ${DIR}/${TOMCAT_FILE} -C ${INSTALL_DIR}
    cd ${INSTALL_DIR} && ln -s apache-tomcat-*/ tomcat
    echo "PATH=${INSTALL_DIR}/tomcat/bin:"'$PATH' > /etc/profile.d/tomcat.sh
    id tomcat &> /dev/null || useradd -r -s /sbin/nologin tomcat

    cat > ${INSTALL_DIR}/tomcat/conf/tomcat.conf <<EOF
JAVA_HOME=${INSTALL_DIR}/jdk
EOF
    
    chown -R tomcat.tomcat ${INSTALL_DIR}/tomcat/

    cat > /lib/systemd/system/tomcat.service <<EOF
[Unit]
Description=Tomcat
#After=syslog.target network.target remote-fs.target nss-lookup.target
After=syslog.target network.target 

[Service]
Type=forking
EnvironmentFile=${INSTALL_DIR}/tomcat/conf/tomcat.conf
ExecStart=${INSTALL_DIR}/tomcat/bin/startup.sh
ExecStop=${INSTALL_DIR}/tomcat/bin/shutdown.sh
RestartSec=3
PrivateTmp=true
User=tomcat
Group=tomcat

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    systemctl enable --now tomcat.service &> /dev/null
    systemctl is-active tomcat.service &> /dev/null && color 0 "TOMCAT 安裝完成" || { color 1 "TOMCAT 安裝失敗" ; exit; }
}


install_jdk
install_tomcat

[root@web2 ~]$ sh install_tomcat.sh 
請輸入JDK版本號:8u321
請輸入Tomcat版本號:9.0.59
java version "1.8.0_321"
Java(TM) SE Runtime Environment (build 1.8.0_321-b07)
Java HotSpot(TM) 64-Bit Server VM (build 25.321-b07, mixed mode)
JDK安裝完成                                                [  OK  ]
TOMCAT 安裝完成                                            [  OK  ]

#創建虛擬主機
[root@web2 ~]$ vi /usr/local/tomcat/conf/server.xml
            pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #在這一行之後添加下麵幾行信息
      <Host name="www.yanlinux.edu" appBase="/data/jpress/" unpackWARs="true" autoDeploy="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
               prefix="jpress_access_log" suffix=".txt"                                                
               pattern="%h %l %u %t &quot;%r&quot; %s %b" />
      </Host>
      #以上信息就是虛擬主機的配置信息
    </Engine>
  </Service>
</Server>

#準備虛擬主機的數據目錄,tomcat預設會在ROOT目錄中找,所以需要將應用數據佈置到這裡面就可以避免在URL中添加應用目錄來訪問了。
[root@web2 ~]$ mkdir /data/webapps/ROOT -p
[root@web2 ~]$ chown -R tomcat.tomcat /data/webapps

[root@web2 ~]$ systemctl restart tomcat.service

7.2 部署nginx

#利用6.1中的安裝nginx腳本來安裝
[root@web2 ~]$ sh install_nginx.sh

#創建子配置目錄
[root@web2 ~]$ mkdir /apps/nginx/conf/conf.d
[root@web2 ~]$ vi /apps/nginx/conf/nginx.conf
#在主配置文件中引入子配置目錄
[root@web2 ~]$ tail -n2 /apps/nginx/conf/nginx.conf
    include /apps/nginx/conf/conf.d/*.conf;
}

#創建業務2配置文件
[root@web2 ~]$ cat /apps/nginx/conf/conf.d/www.yanlinux.edu.conf
server {
    listen 80;
    server_name www.yanlinux.edu;
    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $http_host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

[root@web2 ~]$ nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
[root@web2 ~]$ nginx -s reload

7.3 部署JPress應用

#上官網http://www.jpress.io/下載war包,上傳到伺服器
[root@web2 ~]$ cp jpress-v4.0.7.war /usr/local/tomcat/webapps/jpress.war
[root@web2 ~]$ cd /usr/local/tomcat/webapps/
#war包傳到tomcat目錄下就會自動解包,
[root@web2 webapps]$ ls
docs  examples  host-manager  jpress  jpress.war  manager  ROOT

#然後將jpress/目錄下的內容拷貝到6.7.1創建tomcat虛擬主機www.yanlinux.edu的數據目錄中
[root@web2 ~]$ cp -a /usr/local/tomcat/webapps/jpress/* /data/webapps/ROOT/


#資料庫賬號已經在6.4中創建直接連接就可以

瀏覽器訪問

7.4 掛載NFS伺服器

[root@web2 ~]$ yum -y install nfs-utils
[root@web2 ~]$ showmount -e 10.0.0.68
Export list for 10.0.0.68:
/data/web2 *
/data/www  *

#永久掛載,添加掛載信息
[root@web2 ~]$ vi /etc/fstab
10.0.0.68:/data/web2    /data/webapps/ROOT/attachment/  nfs _netdev     0 0
[root@web2 ~]$ mount -a
[root@web2 ~]$ df -h |grep data
10.0.0.68:/data/web2   70G  2.2G   68G   4% /data/webapps/ROOT/attachment

#發佈文章,添加一張照片測試
[root@web2 ~]$ ll /data/webapps/ROOT/attachment/20230310/
total 560
-rw-r--r-- 1 666 666 569655 Mar 10 11:10 2974a6d37fb04ebfab8c7816d0a8dadd.png

#NFS伺服器上查看
[root@NFS ~]$ ll /data/web2/20230310/
total 560
-rw-r--r-- 1 www www 569655 Mar 10 11:10 2974a6d37fb04ebfab8c7816d0a8dadd.png

#NFS備份伺服器查看
[root@NFS-bak ~]$ ll /data/web2-backup/20230310/
total 560
-rw-r--r-- 1 www www 569655 Mar 10 11:10 2974a6d37fb04ebfab8c7816d0a8dadd.png

7.5 利用redis實現session共用

#準備從官網下載兩個jar包,上傳到lib目錄下,
##下載地址https://github.com/redisson/redisson/tree/master/redisson-tomcat
[root@web2 ~]$ cd /usr/local/tomcat/lib/
[root@web2 lib]$ ls redisson-*
redisson-all-3.20.0.jar  redisson-tomcat-9-3.20.0.jar

#在context.xml最後一行之前加上以下內容
[root@web2 lib]$ vi ../conf/context.xml
    #添加以下信息
    <Manager className="org.redisson.tomcat.RedissonSessionManager"
             configPath="${catalina.base}/conf/redisson.conf"
             readMode="REDIS" updateMode="DEFAULT" broadcastSessionEvents="false"
             keyPrefix=""/>
    #以上信息就是添加的內容
</Context>


#創建redisson.conf文件
[root@web2 lib]$ vi ../conf/redisson.conf
{
    "singleServerConfig":{
        "idleConnectionTimeout":10000,
        "connectTimeout":10000,
        "timeout":3000,
        "retryAttempts":3,
        "retryInterval":1500,
        "password":null,
        "subscriptionsPerConnection":5,
        "clientName":null,
        "address": "redis://10.0.0.88:6379", #redis伺服器地址
        "subscriptionConnectionMinimumIdleSize":1,
        "subscriptionConnectionPoolSize":50,
        "connectionMinimumIdleSize":32,
        "connectionPoolSize":64,
        "database":0,
        "dnsMonitoringInterval":5000
    },
    "threads":0,
    "nettyThreads":0,
    "codec":{
        "class":"org.redisson.codec.JsonJacksonCodec"
    },
    "transportMode":"NIO"
}

[root@web2 lib]$ systemctl restart tomcat.service 

8 KeepAlived+HAProxy服務搭建,實現整體架構

分別在10.0.0.810.0.0.18兩台rocky主機上編譯安裝keepalivedHAProxy兩個服務,實現高可用。

  1. 編譯安裝keepalived
#ka1節點編譯安裝
# 1.安裝依賴
##centos和rocky
[root@ka1 ~]$ yum -y install gcc curl openssl-devel libnl3-devel net-snmp-devel
##ubuntu所需要的依賴下麵兩種:
##ubuntu18.04
[root@ubuntu1804 ~]$ apt -y install gcc curl openssl libssl-dev libpopt-dev daemon build-essential
##ubuntu20.04
[root@ubuntu2004 ~]$ apt -y install make gcc ipvsadm build-essential pkg-config automake autoconf libipset-dev libnl-3-dev libnl-genl-3-dev libssl-dev libxtables-dev libip4tc-dev libip6tc-dev libipset-dev libmagic-dev libsnmp-dev libglib2.0-dev libpcre2-dev libnftnl-dev libmnl-dev libsystemd-dev



# 2.下載源碼包
[root@ka1 ~]$ wget https://keepalived.org/software/keepalived-2.2.7.tar.gz

##解壓
[root@ka1 ~]$ tar xf keepalived-2.2.7.tar.gz



# 3.編譯安裝
[root@ka1 ~]$ cd keepalived-2.2.7/

#選項--disable-fwmark 可用於禁用iptables規則,可訪止VIP無法訪問,無此選項預設會啟用iptables規則
[root@ka1 keepalived-2.2.7]$ ./configure --prefix=/usr/local/keepalived --disable-fwmark
[root@ka1 keepalived-2.2.7]$ make -j 2 && make install

##驗證版本信息
[root@ka1 keepalived-2.2.7]$ /usr/local/keepalived/sbin/keepalived -v
Keepalived v2.2.7 (01/16,2022)

Copyright(C) 2001-2022 Alexandre Cassen, <[email protected]>

Built with kernel headers for Linux 4.18.0
Running on Linux 4.18.0-348.el8.0.2.x86_64 #1 SMP Sun Nov 14 00:51:12 UTC 2021
Distro: Rocky Linux 8.5 (Green Obsidian)

configure options: --prefix=/usr/local/keepalived --disable-fwmark

Config options:  LVS VRRP VRRP_AUTH VRRP_VMAC OLD_CHKSUM_COMPAT INIT=systemd

System options:  VSYSLOG MEMFD_CREATE IPV4_DEVCONF LIBNL3 RTA_ENCAP RTA_EXPIRES RTA_NEWDST RTA_PREF FRA_SUPPRESS_PREFIXLEN FRA_SUPPRESS_IFGROUP FRA_TUN_ID RTAX_CC_ALGO RTAX_QUICKACK RTEXT_FILTER_SKIP_STATS FRA_L3MDEV FRA_UID_RANGE RTAX_FASTOPEN_NO_COOKIE RTA_VIA FRA_PROTOCOL FRA_IP_PROTO FRA_SPORT_RANGE FRA_DPORT_RANGE RTA_TTL_PROPAGATE IFA_FLAGS LWTUNNEL_ENCAP_MPLS LWTUNNEL_ENCAP_ILA NET_LINUX_IF_H_COLLISION LIBIPTC_LINUX_NET_IF_H_COLLISION LIBIPVS_NETLINK IPVS_DEST_ATTR_ADDR_FAMILY IPVS_SYNCD_ATTRIBUTES IPVS_64BIT_STATS VRRP_IPVLAN IFLA_LINK_NETNSID GLOB_BRACE GLOB_ALTDIRFUNC INET6_ADDR_GEN_MODE VRF



# 4.創建service文件
##預設源碼包中會有unit文件,只需要將提供的service文件拷貝到/lib/systemd/system/目錄下即可
[root@ka1 keepalived-2.2.7]$ cp ./keepalived/keepalived.service /lib/systemd/system/
[root@ka1 keepalived-2.2.7]$ cat /lib/systemd/system/keepalived.service 
[Unit]
Description=LVS and VRRP High Availability Monitor
After=network-online.target syslog.target 
Wants=network-online.target 
Documentation=man:keepalived(8)
Documentation=man:keepalived.conf(5)
Documentation=man:genhash(1)
Documentation=https://keepalived.org

[Service]
Type=forking
PIDFile=/run/keepalived.pid
KillMode=process
EnvironmentFile=-/usr/local/keepalived/etc/sysconfig/keepalived
ExecStart=/usr/local/keepalived/sbin/keepalived  $KEEPALIVED_OPTIONS
ExecReload=/bin/kill -HUP $MAINPID

[Install]
WantedBy=multi-user.target


# 5.創建配置文件
##編譯目錄下會自動生成示例配置文件,需要在/etc目錄下建一個keepalived目錄存放配置文件。然後將其中配置VRRP以及real-server的示例信息刪除,只留下global_defs配置語塊即可。
[root@ka1 keepalived-2.2.7]$ mkdir /etc/keepalived
[root@ka1 keepalived-2.2.7]$ cp /usr/local/keepalived/etc/keepalived/keepalived.conf.sample /etc/keepalived/keepalived.conf
##按自己需求修改示例配置文件
[root@ka1 keepalived-2.2.7]$ vi /etc/keepalived/keepalived.conf
global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   notification_email_from [email protected]
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   router_id ka1    #每個keepalived主機唯一標識,建議使用當前主機名,如果多節點重名可能會影響切換腳本執行。在另一臺keepalived主機ka2上,應該改為ka2
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
   vrrp_mcast_group4 230.1.1.1
}
include /etc/keepalived/conf.d/*.conf 	#當生產環境複雜時, /etc/keepalived/keepalived.conf 文件中內容過多,不易管理,可以將不同集群的配置,比如:不同集群的VIP配置放在獨立的子配置文件中。利用include指令可以實現包含子配置文件

##創建子配置文件目錄
[root@ka1 keepalived-2.2.7]$ mkdir /etc/keepalived/conf.d/



# 6.啟動服務
[root@ka1 keepalived-2.2.7]$ systemctl daemon-reload 
[root@ka1 keepalived-2.2.7]$ systemctl enable --now keepalived.service
[root@ka1 keepalived-2.2.7]$ systemctl is-active keepalived
active



# 7.在ka2節點上按照ka1節點操作進行編譯安裝
[root@ka2 ~]$ systemctl is-active keepalived.service 
active

[root@ka2 ~]$ /usr/local/keepalived/sbin/keepalived -v
Keepalived v2.2.7 (01/16,2022)

Copyright(C) 2001-2022 Alexandre Cassen, <[email protected]>

Built with kernel headers for Linux 4.18.0
Running on Linux 4.18.0-348.el8.0.2.x86_64 #1 SMP Sun Nov 14 00:51:12 UTC 2021
Distro: Rocky Linux 8.5 (Green Obsidian)

configure options: --prefix=/usr/local/keepalived --disable-fwmark

Config options:  LVS VRRP VRRP_AUTH VRRP_VMAC OLD_CHKSUM_COMPAT INIT=systemd

System options:  VSYSLOG MEMFD_CREATE IPV4_DEVCONF LIBNL3 RTA_ENCAP RTA_EXPIRES RTA_NEWDST RTA_PREF FRA_SUPPRESS_PREFIXLEN FRA_SUPPRESS_IFGROUP FRA_TUN_ID RTAX_CC_ALGO RTAX_QUICKACK RTEXT_FILTER_SKIP_STATS FRA_L3MDEV FRA_UID_RANGE RTAX_FASTOPEN_NO_COOKIE RTA_VIA FRA_PROTOCOL FRA_IP_PROTO FRA_SPORT_RANGE FRA_DPORT_RANGE RTA_TTL_PROPAGATE IFA_FLAGS LWTUNNEL_ENCAP_MPLS LWTUNNEL_ENCAP_ILA NET_LINUX_IF_H_COLLISION LIBIPTC_LINUX_NET_IF_H_COLLISION LIBIPVS_NETLINK IPVS_DEST_ATTR_ADDR_FAMILY IPVS_SYNCD_ATTRIBUTES IPVS_64BIT_STATS VRRP_IPVLAN IFLA_LINK_NETNSID GLOB_BRACE GLOB_ALTDIRFUNC INET6_ADDR_GEN_MODE VRF
  1. 編譯安裝HAProxy服務

    編譯安裝HAProxy 2.6 LTS版本,更多源碼包下載地址:http://www.haproxy.org/download/

    依賴lua環境,由於CentOS7 之前版本自帶的lua版本比較低並不符合HAProxy要求的lua最低版本(5.3)的要求,因此需要編譯安裝較新版本的lua環境,然後才能編譯安裝HAProxy。

#ka1節點安裝HAProxy
# 1.安裝依賴環境
##centos或rocky
[root@ka1 ~]$ yum -y install gcc make gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel libtermcap-devel ncurses-devel libevent-devel readline-devel
##ubuntu
apt -y install gcc make openssl libssl-dev libpcre3 libpcre3-dev zlib1g-dev  libreadline-dev libsystemd-dev



# 2.編譯安裝lua環境
##下載源碼:參考鏈接http://www.lua.org/start.html
[root@ka1 ~]$ curl -R -O http://www.lua.org/ftp/lua-5.4.4.tar.gz
[root@ka1 ~]$ tar xvf lua-5.3.5.tar.gz -C /usr/local/src
[root@ka1 ~]$ cd /usr/local/src/lua-5.3.5
[root@ka1 lua-5.3.5]$ make all test
[root@ka1 lua-5.3.5]$ pwd
/usr/local/src/lua-5.3.5
[root@ka1 lua-5.3.5]$ ./src/lua -v
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio



# 3.編譯安裝haproxy
##下載源碼:官網鏈接:www.haproxy.org
[root@ka1 ~]$ https://www.haproxy.org/download/2.6/src/haproxy-2.6.9.tar.gz
[root@ka1 ~]$ tar xvf haproxy-2.6.9.tar.gz -C /usr/local/src
[root@ka1 ~]$ cd /usr/local/src/haproxy-2.6.9

##編譯安裝
[root@ka1 haproxy-2.6.9]$ make ARCH=x86_64 TARGET=linux-glibc USE_PCRE=1 USE_OPENSSL=1 USE_ZLIB=1 USE_SYSTEMD=1 USE_CPU_AFFINITY=1 USE_LUA=1 LUA_INC=/usr/local/src/lua-5.3.5/src/ LUA_LIB=/usr/local/src/lua-5.3.5/src/ PREFIX=/apps/haproxy
[root@ka1 haproxy-2.6.9]$ make install PREFIX=/apps/haproxy

##解決環境變數
[root@ka1 haproxy-2.6.9]$ ln -s /apps/haproxy/sbin/haproxy /usr/sbin/

##驗證haproxy版本
[root@ka1 haproxy-2.6.9]$ which haproxy 
/usr/sbin/haproxy
[root@ka1 haproxy-2.6.9]$ haproxy -v
HAProxy version 2.6.9-3a3700a 2023/02/14 - https://haproxy.org/
Status: long-term supported branch - will stop receiving fixes around Q2 2027.
Known bugs: http://www.haproxy.org/bugs/bugs-2.6.9.html
Running on: Linux 4.18.0-348.el8.0.2.x86_64 #1 SMP Sun Nov 14 00:51:12 UTC 2021 x86_64



# 4.創建HAProxy配置文件
[root@ka1 haproxy-2.6.9]$ cd
##準備配置文件目錄
[root@ka1 ~]$ mkdir /etc/haproxy
[root@ka1 ~]$ cat > /etc/haproxy/haproxy.cfg <<EOF
global
    maxconn 100000
    stats socket /var/lib/haproxy/haproxy.sock mode 600 level admin
    uid 99    #指定運行haproxy的用戶身份
    gid 99    #指定運行haproxy的用戶身份
    daemon    #以守護進程運行
    nbthread 2  #指定每個haproxy進程開啟的線程數,預設為每個進程一個線程
    cpu-map 1/all 0-1    ##haproxy2.4中啟用nbthreads,在global配置中添加此選項,可以進行線程和CPU的綁定
    pidfile /var/lib/haproxy/haproxy.pid
    log 127.0.0.1 local3 info

defaults
    option http-keep-alive    #開啟與客戶端的會話保持
    option forwardfor         #透傳客戶端真實IP至後端web伺服器
    maxconn 100000
    mode http				  #設置預設工作類型,使用TCP伺服器性能更好,減少壓力
    timeout connect 300000ms  #客戶端請求從haproxy到後端server最長連接等待時間(TCP連接之前),預設單位ms
    timeout client 300000ms   #設置haproxy與客戶端的最長非活動時間,預設單位ms,建議和timeoutserver相同 
    timeout server 300000ms   #客戶端請求從haproxy到後端服務端的請求處理超時時長(TCP連接之後),預設單位ms,如果超時,會出現502錯誤,此值建議設置較大些,防止出現502錯誤

listen stats
    mode http					#http協議
    bind 10.0.0.8:9999          #對外發佈的IP及埠。#指定HAProxy的監聽地址,可以是IPV4或IPV6,可以同時監聽多個IP或埠。在ka2主機上該項應該改為自己主機的IP地址
    stats enable
    log global
    stats uri /haproxy-status
    stats auth admin:123456
EOF

##準備socket文件目錄
[root@ka1 ~]$ mkdir -p /var/lib/haproxy


# 5.創建用戶及組
[root@ka1 ~]$ groupadd -g 99 haproxy
[root@ka1 ~]$ useradd -u 99 -g haproxy -d /var/lib/haproxy -M -r -s /sbin/nologin haproxy


# 6.創建服務啟動service文件
[root@ka1 ~]$ cat > /lib/systemd/system/haproxy.service <<EOF
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -c -q
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /var/lib/haproxy/haproxy.pid
ExecReload=/bin/kill -USR2 $MAINPID

[Install]
WantedBy=multi-user.target
EOF


# 7.使用子配置文件保存配置
## 當業務眾多時,將所有配置都放在一個配置文件中,會造成維護困難。可以考慮按業務分類,將配置信息拆分,放在不同的子配置文件中,從而達到方便維護的目的。

##創建子配置目錄
[root@ka1 ~]$ mkdir /etc/haproxy/conf.d
##添加子配置文件目錄到service文件中
[root@ka1 ~]$ vi /lib/systemd/system/haproxy.service
[Unit]
Description=HAProxy Load Balancer
After=syslog.target network.target

[Service]
ExecStartPre=/usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d -c -q   #這一行添加-f 子配置文件目錄
ExecStart=/usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -f /etc/haproxy/conf.d -p /var/lib/haproxy/haproxy.pid #這一行添加-f 子配置文件目錄
ExecReload=/bin/kill -USR2

[Install]
WantedBy=multi-user.target


# 8.修改內核參數,讓haproxy bind在非本機的ip上(也就是Keepalived產生的VIP),在keepalived從節點上,剛開始是沒有這個IP的,如果不修改這個內核參數,啟動不了haproxy服務
[root@ka1 ~]$ vi /etc/sysctl.conf
net.ipv4.ip_nonlocal_bind = 1 #添加這一行
#使內核參數生效
[root@ka1 ~]$ sysctl -p
net.ipv4.ip_nonlocal_bind = 1


# 9.啟動服務
[root@ka1 ~]$ systemctl daemon-reload
[root@ka1 ~]$ systemctl enable --now haproxy
###現在就可以在子配置目錄中根據不同的業務來創建對應的配置文件了。



# 10.ka2節點按照ka1節點安裝操作從頭做一遍
  1. 創建兩個不同業務的配置文件
#ka1節點配置
##keepalived子配置文件
[root@ka1 ~]$ cd /etc/keepalived/conf.d/

##創建haproxy檢測腳本
[root@ka1 ~]$ cat /etc/keepalived/conf.d/check_haproxy.sh
#!/bin/bash
/usr/bin/killall -0 haproxy || systemctl restart haproxy
##添加執行許可權
[root@ka1 ~]$ chmod a+x /etc/keepalived/conf.d/check_haproxy.sh

##創建郵件通知腳本
[root@ka1 ~]$ cat /etc/keepalived/notify.sh 
#!/bin/bash
contact='[email protected]'
email_send='[email protected]'
email_passwd='zzvjrqnkrkafbaec'
email_smtp_server='smtp.qq.com'

. /etc/os-release

msg_error() {
    echo -e "\033[1;31m$1\033[0m"
}

msg_info() {
    echo -e "\033[1;32m$1\033[0m"
}

msg_warn() {
echo -e "\033[1;33m$1\033[0m"
}

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $" OK "
    elif [ $2 = "failure" -o $2 = "1" ] ;then
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo
}

install_sendemail () {
    if [[ $ID =~ rhel|centos|rocky ]];then
        rpm -q sendemail &> /dev/null || yum -y install sendemail
    elif [ $ID = 'ubuntu' ];then
        dpkg -l | grep -q sendemail || { apt update; apt -y install libio-socket-ssl-perl libnet-ssleay-perl sendemail; }
    else
        color "不支持此操作系統,退出!" 1
        exit
    fi
}

send_mail() {
    local email_receive="$1"
    local email_subject="$2"
    local email_message="$3"
    sendemail -f $email_send -t $email_receive -u $email_subject -m $email_message -s $email_smtp_server -o message-charset=utf-8 -o tls=yes -xu $email_send -xp $email_passwd
    [ $? -eq 0 ] && color "郵件發送成功" 0 || color "郵件發送失敗" 1
}

notify() {
    if [[ $1 =~ ^(master|backup|fault)$ ]];then
        mailsubject="$(hostname) to be $1, vip floating"
        mailbody="$(date +'%F %T'): vrrp transition, $(hostname) changed to be $1"
        send_mail "$contact" "$mailsubject" "$mailbody"
    else
        echo "Usage: $(basename $0) {master|backup|fault}"
        exit 1
    fi
}

install_sendemail
notify $1
##加執行許可權
[root@ka1 ~]$ chmod a+x /etc/keepalived/notify.sh


##創建子配置文件
[root@ka1 conf.d]$ cat web.conf 
vrrp_script check_haproxy {
    script "/etc/keepalived/conf.d/check_haproxy.sh"  ##shell命令或腳本路徑
    interval 1			#間隔時間,單位為秒,預設1秒
    weight -30			#預設為0,如果設置此值為負數,當上面腳本返回值為非0時,會將此值與本節點權重相加可以降低本節點權重,即表示fall. 如果是正數,當腳本返回值為0,會將此值與本節點權重相加可以提高本節點權重,即表示 rise.通常使用負值
    fall 3				#執行腳本連續幾次都失敗,則轉換為失敗,建議設為2以上
    rise 2				#執行腳本連續幾次都成功,把伺服器從失敗標記為成功
    timeout 2			#超時時間
}

vrrp_instance VI_1 {
    state MASTER			#當前節點在此虛擬路由器上的初始狀態,狀態為MASTER,在ka2主機上要設置為BACKUP
    interface eth0     		#綁定為當前虛擬路由器使用的物理介面
    virtual_router_id 51	#每個虛擬路由器唯一標識,範圍:0-255,每個虛擬路由器此值必須唯一,否則服務無法啟動,同屬一個虛擬路由器的多個keepalived節點必須相同,務必要確認在同一網路中此值必須唯一
    priority 100			#當前物理節點在此虛擬路由器的優先順序,範圍:1-254,每個keepalived主機節點此值不同。ka2主機要設置為80			
    advert_int 1			#vrrp通告的時間間隔,預設1s
    authentication {		#認證機制
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {		#虛擬IP,生產環境可能指定上百個IP地址
        10.0.0.200 dev eth0 label eth0:1  #指定VIP的網卡label
    }
    unicast_src_ip 10.0.0.8 	#指定發送單播的源IP
    unicast_peer{
        10.0.0.18				#指定接收單播的對方目標主機IP
    }
    notify_master "/etc/keepalived/notify.sh master"  	#當前節點成為主節點時觸發的腳本
    notify_backup "/etc/keepalived/notify.sh backup"	#當前節點轉為備節點時觸發的腳本
    notify_fault "/etc/keepalived/notify.sh fault"		#當前節點轉為“失敗”狀態時觸發的腳本
    track_script {
        check_haproxy    #調用腳本
    }
}


##創建haproxy業務子配置文件
## 註意: 子配置文件的文件尾碼必須為.cfg
[root@ka1 ~]$ cd /etc/haproxy/conf.d/
[root@ka1 conf.d]$ cat web.cfg 
frontend http_80
    bind 10.0.0.200:80
    acl org_domain hdr_dom(host) -i www.yanlinux.org
    acl edu_domain hdr_dom(host) -i www.yanlinux.edu
    use_backend www.yanlinux.org if org_domain
    use_backend www.yanlinux.edu if edu_domain
    
backend www.yanlinux.org
    server 10.0.0.28 10.0.0.28:80 check inter 3000 fall 3 rise 5

backend www.yanlinux.edu
    server 10.0.0.38 10.0.0.38:80 check inter 3000 fall 3 rise 5

##重啟服務
[root@ka1 ~]$ systemctl restart keepalived.service haproxy.service


#ka2節點配置
##keepalived業務子配置文件
##從ka1節點上拷貝郵件通知腳本和haproxy檢查腳本到本機上
[root@ka2 ~]$ scp 10.0.0.8:/etc/keepalived/notify.sh /etc/keepalived/
[root@ka2 ~]$ scp 10.0.0.8:/etc/keepalived/conf.d/check_haproxy.sh /etc/keepalived/conf.d/

##創建子配置文件,大致上與ka1節點上的配置相同
[root@ka2 ~]$ cat /etc/keepalived/conf.d/web.conf
vrrp_script check_haproxy {
    script "/etc/keepalived/conf.d/check_haproxy.sh"
    interval 1
    weight -30
    fall 3
    rise 2
    timeout 2
}

vrrp_instance VI_1 {
    state BACKUP         #這裡改為BACKUP
    interface eth0
    virtual_router_id 51
    priority 80			 #改為80,因為是從節點
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.0.0.200 dev eth0 label eth0:1 
    }
    unicast_src_ip 10.0.0.18
    unicast_peer {
        10.0.0.8
    }
    notify_master "/etc/keepalived/notify.sh master"
    notify_backup "/etc/keepalived/notify.sh backup"
    notify_fault "/etc/keepalived/notify.sh fault"
    track_script {
        check_haproxy
    }
}

##創建haproxy業務子配置文件,直接從ka1節點拷貝過來就行
[root@ka2 ~]$ scp 10.0.0.8:/etc/haproxy/conf.d/web.cfg /etc/haproxy/conf.d

##重啟服務
[root@ka2 ~]$ systemctl restart keepalived.service haproxy.service

兩台keepalived狀態頁信息,測試keepalived業務搭建成功

9 整體架構完成,業務訪問測試

[root@internet ~]$ curl -I www.yanlinux.org
HTTP/1.1 200 OK
server: nginx
date: Fri, 10 Mar 2023 06:36:29 GMT
content-type: text/html; charset=utf-8
set-cookie: KOD_SESSION_ID=aae53db9278d6386198b98a7a0441608; expires=Fri, 10-Mar-2023 10:36:29 GMT; Max-Age=14400; path=/; HttpOnly
set-cookie: CSRF_TOKEN=FGJc4urT5PVxmrWT; expires=Fri, 17-Mar-2023 06:36:29 GMT; Max-Age=604800; path=/

[root@internet ~]$ curl -I www.yanlinux.edu
HTTP/1.1 200 
server: nginx/1.22.1
date: Fri, 10 Mar 2023 06:38:27 GMT
content-type: text/html;charset=UTF-8
set-cookie: csrf_token=c871c9a8e1e34c38a7773ad96cea0f09; Path=/

網頁瀏覽器查看


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本次使用 SqlConnection 來連接資料庫,使用 DataGridView 來顯示查詢的結果。最終效果如下: 一、連接資料庫 1.獲取連接資料庫所需的字元串,包括伺服器名稱,資料庫名稱,用戶名以及密碼,可在配置文件中配置,或直接在代碼里寫死 在配置文件 App.config 中配置的代碼: ...
  • 前言 ASP.NET Core Web API 介面限流、限制介面併發數量,我也不知道自己寫的有沒有問題,拋磚引玉、歡迎來噴! 需求 寫了一個介面,參數可以傳多個人員,也可以傳單個人員,時間範圍限制最長一個月。簡單來說,當傳單個人員時,介面耗時很短,當傳多個人員時,一般人員會較多,介面耗時較長,一般 ...
  • 在 C# 使用 Solr 搜索 sitecore 的配置信息文件可直接丟進 <Instance>\App_Config 下,sitecore 會自動檢測配置文件更新並載入到記憶體中。 通常情況下,配置信息文件是放在 <Instance>\App_Config\Include\<Project> 下,< ...
  • 1. EF Core簡介Entity Framework (EF) Core 是輕量化、可擴展、開源和跨平臺版的常用 Entity Framework 數據訪問技術。 EF Core 可用作對象關係映射程式 (O/RM),這可以實現以下兩點: 使 .NET 開發人員能夠使用 .NET 對象處理資料庫 ...
  • 如果熟悉 GIthub 我們經常可以在一些開源項目的 PR 上看到會配置測試的驗證以及覆蓋率的報告,並且可以強制覆蓋率不低於設定的值才可以進行 Merge PR。 1.測試 創建一個 xUnit 單元測試項目。 Class /// <summary> /// Represents a class w ...
  • 在合宙上買了一片1.54寸的墨水屏一直在吃灰, 這次趁點亮的機會把AIR32F103上的驅動示例給做了. 將微雪的墨水屏驅動移植到 AIR32F103 上, 代碼已經提交到 GitHub 倉庫, 如果需要驅動其它型號的墨水屏, 編輯 EPD_Config.h 將 #define EPD_1IN54 ... ...
  • LVGL是嵌入式設備中常用的圖形顯示庫, 這篇基於 256K Flash 的 AIR32F103CCT6 和 SPI介面的 ST7735 128x160 LCD屏, 介紹 LVGL 在無系統環境和FreeRTO環境, 帶DMA和不帶DMA方式的集成步驟 ...
  • 準備工作:樹莓派4B一個,記憶體不小於16G的TF卡一個,樹莓派的充電線一個,筆記本電腦一臺,網線一根,讀卡器一個 #1、格式化TF卡 建議選擇16G以上的TF卡,下載格式化工具 選擇要格式化的TF所在的分區 滑鼠右鍵點擊箭頭所指的區域選擇刪除分區,將boot和rootfs兩個分區都刪除乾凈,點擊保存 ...
一周排行
    -Advertisement-
    Play Games
  • GoF之工廠模式 @目錄GoF之工廠模式每博一文案1. 簡單說明“23種設計模式”1.2 介紹工廠模式的三種形態1.3 簡單工廠模式(靜態工廠模式)1.3.1 簡單工廠模式的優缺點:1.4 工廠方法模式1.4.1 工廠方法模式的優缺點:1.5 抽象工廠模式1.6 抽象工廠模式的優缺點:2. 總結:3 ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 本章將和大家分享ES的數據同步方案和ES集群相關知識。廢話不多說,下麵我們直接進入主題。 一、ES數據同步 1、數據同步問題 Elasticsearch中的酒店數據來自於mysql資料庫,因此mysql數據發生改變時,Elasticsearch也必須跟著改變,這個就是Elasticsearch與my ...
  • 引言 在我們之前的文章中介紹過使用Bogus生成模擬測試數據,今天來講解一下功能更加強大自動生成測試數據的工具的庫"AutoFixture"。 什麼是AutoFixture? AutoFixture 是一個針對 .NET 的開源庫,旨在最大程度地減少單元測試中的“安排(Arrange)”階段,以提高 ...
  • 經過前面幾個部分學習,相信學過的同學已經能夠掌握 .NET Emit 這種中間語言,並能使得它來編寫一些應用,以提高程式的性能。隨著 IL 指令篇的結束,本系列也已經接近尾聲,在這接近結束的最後,會提供幾個可供直接使用的示例,以供大伙分析或使用在項目中。 ...
  • 當從不同來源導入Excel數據時,可能存在重覆的記錄。為了確保數據的準確性,通常需要刪除這些重覆的行。手動查找並刪除可能會非常耗費時間,而通過編程腳本則可以實現在短時間內處理大量數據。本文將提供一個使用C# 快速查找並刪除Excel重覆項的免費解決方案。 以下是實現步驟: 1. 首先安裝免費.NET ...
  • C++ 異常處理 C++ 異常處理機制允許程式在運行時處理錯誤或意外情況。它提供了捕獲和處理錯誤的一種結構化方式,使程式更加健壯和可靠。 異常處理的基本概念: 異常: 程式在運行時發生的錯誤或意外情況。 拋出異常: 使用 throw 關鍵字將異常傳遞給調用堆棧。 捕獲異常: 使用 try-catch ...
  • 優秀且經驗豐富的Java開發人員的特征之一是對API的廣泛瞭解,包括JDK和第三方庫。 我花了很多時間來學習API,尤其是在閱讀了Effective Java 3rd Edition之後 ,Joshua Bloch建議在Java 3rd Edition中使用現有的API進行開發,而不是為常見的東西編 ...
  • 框架 · 使用laravel框架,原因:tp的框架路由和orm沒有laravel好用 · 使用強制路由,方便介面多時,分多版本,分文件夾等操作 介面 · 介面開發註意欄位類型,欄位是int,查詢成功失敗都要返回int(對接java等強類型語言方便) · 查詢介面用GET、其他用POST 代碼 · 所 ...
  • 正文 下午找企業的人去鎮上做貸後。 車上聽同事跟那個司機對罵,火星子都快出來了。司機跟那同事更熟一些,連我在內一共就三個人,同事那一手指桑罵槐給我都聽愣了。司機也是老社會人了,馬上聽出來了,為那個無辜的企業經辦人辯護,實際上是為自己辯護。 “這個事情你不能怪企業。”“但他們總不能讓銀行的人全權負責, ...