第11周作业

1.总结 LVS的NAT和DR模型工作原理,并完成DR模型实战。

LVS(Linux Virtual Server)是一个高性能的负载均衡解决方案,它可以在Linux内核中实现。LVS支持多种工作模式,其中最常用的是NAT(网络地址转换)和DR(直接路由)两种模式

  • NAT模式的工作原理:

    • 在NAT模型中,所有的客户端的请求都首先发送到LVS的前端服务器,也就是负载均衡器。负载均衡器接收到请求后,会修改请求数据包的目标IP地址为实际提供服务的后端服务器的IP地址,并将源IP地址改为自己的IP地址,然后转发给后端服务器。
      • 客户端发出的数据包目标是负载均衡器的VIP(虚拟IP)。
      • 负载均衡器接收到数据包后,通过修改数据包头部信息(源IP为目标IP,目标IP为选定的真实服务器IP),并记录下这个映射关系。
      • 后端服务器处理完请求后,响应的数据包发回给负载均衡服务器。
      • 负载均衡服务器根据之前记录的映射关系,把响应的数据包的源地址改回为VIP,再发送给客户端。
    • NAT模式的优点是配置简单,不需要特殊的网络配置;
    • 缺点是负载均衡器可能成为性能瓶颈,以及它为每个连接维护一个NAT表,可能会占用大量系统资源。
  • DR模式的工作原理

    • DR模型中,客户端请求同样先到达负载均衡器,但负载均衡器不会修改数据包的内容,而是只改变MAC地址为选定的后端服务器的MAC地址,然后将数据包发送出去。在这种模式下,所有的真实服务器和负载均衡器必须位于同一个物理网络段上,以便它们可以直接通信,而不需要经过路由器。
      • 所有真实服务器和负载均衡器共享同一个VIP,但是只有负载均衡器对这个VIP作出ARP响应。
      • 当客户端向VIP发起请求时,请求被发送到负载均衡器
      • 负载均衡器不修改IP头部,只更改二层的MAC地址为目标服务器的MAC地址,然后转发给真实服务器。
      • 真实服务器处理完请求后,直接用VIP作为源地址回应客户端,这样不需要再次经过负载均衡器。
    • DR模型的优点是可以让后端服务器直接响应客户端,从而减轻了负载均衡器的压力。
    • 缺点是要求所有的真实服务器与负载均衡器在同一个广播域内,对网络拓扑有一定的限制

DR模型实现: 架构设计如上图

1、client 配置

bash 复制代码
#网关指向router
[root@client: ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.200  0.0.0.0         UG    0      0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth0

2、router配置

bash 复制代码
[root@router: ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
192.168.10.0    0.0.0.0         255.255.255.0   U     0      0        0 eth1

#开启路由转发功能
[root@router: ~]# echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
[root@router: ~]# sysctl -p
net.ipv4.ip_forward = 1

3、lvs配置

bash 复制代码
[root@lvs: ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.212      0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0

4、rs-1 rs-2配置

bash 复制代码
[root@rs-1: ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.212      0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0
[root@rs-2: ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.0.0.212      0.0.0.0         UG    0      0        0 eth0
10.0.0.0        0.0.0.0         255.255.255.0   U     0      0        0 eth0

5、客户端主机测试

bash 复制代码
#在客户端测试,两台后台RS服务器能访问;此时LVS主机上的VIP还没配置
[root@client: ~]# curl 10.0.0.214
This page from rs-1
[root@client: ~]# curl 10.0.0.215
This page from rs-2
[root@client: ~]# 

6、配置VIP和转发规则

bash 复制代码
#rs-1 rs-2上配置VIP
[root@rs-1: ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 
[root@rs-1: ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@rs-1: ~]# ifconfig lo:1 10.0.0.100 netmask 255.255.255.255

[root@rs-2: ~]# echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore 
[root@rs-2: ~]# echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@rs-2: ~]# ifconfig lo:1 10.0.0.100 netmask 255.255.255.255

#LVS 主机上配置VIP
[root@lvs: ~]# ifconfig loifconfig lo:1 10.0.0.100 netmask 255.255.255.255

#LVS 主机上配置转发规则
[root@lvs: ~]# ipvsadm -A -t 10.0.0.100:80 -s wrr
[root@lvs: ~]# ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.214 -g -w 1
[root@lvs: ~]# ipvsadm -a -t 10.0.0.100:80 -r 10.0.0.215 -g -w 1

#查看
[root@lvs: ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  10.0.0.100:80 wrr
  -> 10.0.0.214:80                Route   1      0          0         
  -> 10.0.0.215:80                Route   1      0          0         

7、客户端测试转发

bash 复制代码
[root@client: ~]# curl 10.0.0.100
This page from rs-2
[root@client: ~]# curl 10.0.0.100
This page from rs-1

2.总结LVS的调度算法

调度算法分为静态算法和动态算法两类,实际使用较多的是 RR,WRR,WLC等几种

四种静态调度算法

静态算法仅根据算法本身来进行调度,不关注后端RS服务器负载情况

  • RR:Round Robin,轮询算法,LVS 服务器将前端请求轮流转发到后端每一台 RS 服务器上,后端每台 RS 服务器的请求量都是相同的。
  • WRR:Weight RR,加权轮询算法,LVS 服务器将前端请求根据后端 RS 服务器的权重进行转发,对于后端 RS 服务中性能好的机器可以设置较高的权重,物尽其用。
  • SH:Source Hash,源 IP 地址 hash,将来自同一个 IP 地址的客户端请求调度到后端同一台 RS 服务器上,从而实现会话保持
  • DH:Destination Hash,目标 IP 地址 hash,客户端的请求第一次被调度到某后端 RS 服务器后,其后续的请求都将会被发往同一台 RS 服务器,一般用于正向代理缓存场景。

六种动态调度算法

动态算法要根据当前系统中后端 RS 服务器的负载情况进行调度,给负载较低的后端主机多转发,给负载较高的后端主机少转发。

  • LC:Least Connections,最少连接,将新的请求分配给当前活跃连接数最少的真实服务器;适用于处理长时间连接的服务,如数据库查询或文件传输。
  • WLC::Weighted Least Connections,加权最少连接,在考虑服务器当前活跃连接数量的基础上加入了权重的概念;权重较高的服务器在相同连接数时更有可能被选中。
  • SED:Shortest Expected Delay,最短预期延迟,考虑了服务器当前的活跃连接数和新连接建立的时间成本。它尝试预测哪台服务器能够最快地开始处理下一个请求。
  • NQ:Never Queue,最少队列调度算法,初始的时候先做一次轮循,保证每台 RS 都至少被调度一次,后续使用 SED 调度算法
  • LBLC:Locality-Based Least Connections,基于局部性的最少链接调度算法,本质是动态的 DH算法,该算法优先使用 DH 算法将请求调度到同一台 RS 服务器上,如果该 RS 服务器负载较高或不可用,则再使用 LC 算法决定调度到哪一台 RS 服务器上,此 RS 服务器将成为一下次调度时 DH算法的首选项
  • LBLCR:Locality-Based Least Connections with Replication,快速响应优选,结合地理位置信息与最少连接原则,倾向于选择地理个更近的服务器;支持多站点部署,可增加用户体验。

架构部分第1周作业

1.在虚拟机安装tomcat并且部署一个服务,并且实现会话共享。

1、架构设计

2、安装tomcat

bash 复制代码
#下载JDK和tomcat二进制包

#使用脚本离线安装tomcat
#!/bin/bash
#离线安装JDK和TOMCAT
TOMCAT_VERSION=9.0.98
JDK_VERSION=8u391
TOMCAT_FILE="apache-tomcat-${TOMCAT_VERSION}.tar.gz"
JDK_FILE="jdk-${JDK_VERSION}-linux-x64.tar.gz"
JDK_DIR="/usr/local"
TOMCAT_DIR="/usr/local"
DIR=`pwd`

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 [ -d $JDK_DIR/jdk ];then
    color 1  "JDK 已经安装" 
    exit
else 
    [ -d "$JDK_DIR" ] || mkdir -pv $JDK_DIR
fi
tar xvf $DIR/$JDK_FILE  -C $JDK_DIR
cd  $JDK_DIR && ln -s jdk* jdk 

cat >  /etc/profile.d/jdk.sh <<EOF
export JAVA_HOME=$JDK_DIR/jdk
export PATH=\$PATH:\$JAVA_HOME/bin
#export JRE_HOME=\$JAVA_HOME/jre
#export CLASSPATH=.:\$JAVA_HOME/lib/:\$JRE_HOME/lib/
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 [ -d $TOMCAT_DIR/tomcat ];then
    color 1 "TOMCAT 已经安装" 
    exit
else 
    [ -d "$TOMCAT_DIR" ] || mkdir -pv $TOMCAT_DIR
fi
tar xf $DIR/$TOMCAT_FILE -C $TOMCAT_DIR
cd  $TOMCAT_DIR && ln -s apache-tomcat-*/  tomcat
echo "PATH=$TOMCAT_DIR/tomcat/bin:"'$PATH' > /etc/profile.d/tomcat.sh
id tomcat &> /dev/null || useradd -r -s /sbin/nologin tomcat

cat > $TOMCAT_DIR/tomcat/conf/tomcat.conf <<EOF
JAVA_HOME=$JDK_DIR/jdk
EOF

chown -R tomcat.tomcat $TOMCAT_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=$TOMCAT_DIR/tomcat/conf/tomcat.conf
ExecStart=$TOMCAT_DIR/tomcat/bin/startup.sh
ExecStop=$TOMCAT_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

3、配置tomcat服务器,准备测试页面

bash 复制代码
#在tomcat两台服务器上创建两个测试页面
vim /usr/local/tomcat/webapps/ROOT/test.jsp

<%@ page import="java.util.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>tomcat test</title>
</head>
<body>
<h1> Tomcat Website </h1>
<div>On <%=request.getServerName() %></div>
<div><%=request.getLocalAddr() + ":" + request.getLocalPort() %></div>
<div>SessionID = <span style="color:blue"><%=session.getId() %></span></div>
<%=new Date()%>
</body>
</html>

4、配置proxy服务器

bash 复制代码
#修改hosts文件模拟DNS解析tomcat-1和tomcat-2
vim /etc/hosts	#添加以下两行
127.0.0.1 tomcat.hui.cn
10.0.0.212 tomcat01.hui.cn
10.0.0.213 tomcat02.hui.cn

#修改nginx配置文件,实现负载均衡到后端的 Tomcat 服务器(通过处理以 .jsp 或 .do 结尾的请求)
http {	#添加以下内容到http段中,

    upstream tomcat-servers {
        server tomcat01.hui.cn:8080;
        server tomcat02.hui.cn:8080;
    }

    server {
        listen 80;
        server_name tomcat.hui.cn;
        location ~* \.(jsp|do)$ {
            proxy_pass http://tomcat-servers;
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
#测试配置文件并重新加载配置
nginx -t
nginx -s reload

5、配置 redis

bash 复制代码
1)安装redis
apt update && apt install -y redis-server
2)修改监听端口
vim /etc/redis/redis.conf
bind 0.0.0.0
3) systemctl restart redis-server.service

6、配置 redission

bash 复制代码
1) Add session manager(添加会话管理)
#在tomcat-1和tomcat-2上:
vim /usr/local/tomcat/conf/context.xml
#最后一行前添加以下内容
<Manager className="org.redisson.tomcat.RedissonSessionManager"
             configPath="${catalina.base}/conf/redisson.conf" readMode="MEMORY"
             updateMode="DEFAULT"/>
#创建文件
vim /usr/local/tomcat/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.214: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"
}
---------------------------------------------------------------------------------
2)Copy two jars into TOMCAT_BASE/lib directory:(下载两个jar包到	/usr/local/tomcat/lib/)
curl -LO https://repo1.maven.org/maven2/org/redisson/redisson-all/3.38.1/redisson-all-3.38.1.jar

curl -LO https://repo1.maven.org/maven2/org/redisson/redisson-tomcat-9/3.38.1/redisson-tomcat-9-3.38.1.jar

mv redisson-* /usr/local/tomcat/lib/

7、测试

1)从物理机访问代理服务器,被负载均衡调度到后端的两台tomcat服务器上,但是"SessionID"并没有改变,实现了会话共享。

2)使用工具连接至redis服务器查看数据

3)访问 redis 服务器,查看生成的数据

bash 复制代码
[root@redission: ~]# redis-cli 
127.0.0.1:6379> KEYS *
1) "redisson:tomcat_session:57F5A555B97E9C2C336D98A291193A9E"
127.0.0.1:6379> type "redisson:tomcat_session:57F5A555B97E9C2C336D98A291193A9E"
hash
127.0.0.1:6379> hgetall redisson:tomcat_session:57F5A555B97E9C2C336D98A291193A9E
 1) "session:thisAccessedTime"
 2) "[\"java.lang.Long\",1734883477216]"
 3) "session:isNew"
 4) "false"
 5) "session:lastAccessedTime"
 6) "[\"java.lang.Long\",1734883477216]"
 7) "session:maxInactiveInterval"
 8) "1800"
 9) "session:isValid"
10) "true"
11) "session:creationTime"
12) "[\"java.lang.Long\",1734883470051]"
127.0.0.1:6379> 

2.总结JVM内存结构和垃圾回收算法。

JVM的内存主要分为以下几个区域:

  1. 堆(Heap Memory):
    • 这是Java对象实例化的地方,所有通过new关键字创建的对象都存储在这里。
    • 堆被进一步细分为新生代(Young Generation)、老年代(Old Generation)。
      • 新生代又被分为Eden区和两个Survivor区(From和To)。
      • 老年代用于存放经历多次垃圾回收后仍然存活的对象。
  2. 方法区(Method Area):
    • 也称为永久代(PermGen)或元空间(Metaspace),用于存储类信息、常量、静态变量等数据。
    • 在JDK8之后,永久代被移除,取而代之的是元空间,并且它位于本地内存中。
  3. 栈(Stack Memory):
    • 每个 线程都有一个私有的栈,包含若干个栈帧(Frame),每个方法调用对应一个栈帧。
    • 栈帧中保存了局部变量表、操作数栈、动态链接、方法出口等信息。
  4. 程序计数器(Program Counter Register):
    • 每个线程都有自己的程序计数器,用来记录当前线程执行的字节码指令地址。
    • 如果线程正在执行的是一个Java方法,计数器记录的是JVM指令地址;如果是Native方法,则此计数器值为空(Undefined)。
  5. 本地方法栈(Native Method Stack):
    • 类似于Java栈,但它是为本地方法服务的,即使用JNI(Java Native Interface)编写的代码。

垃圾回收算法

JVM提供了多种垃圾回收算法来自动管理堆内存,减少程序员手动管理内存的工作量。常见的垃圾回收算法包括:

  1. 标记-清除(Mark-Sweep):
    • 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
    • 缺点是效率低,会产生内存碎片。
  2. 复制(Copying):
    • 将存活的对象复制到另一块内存区域,适用于新生代中的对象,因为大多数对象在创建后很快就会变得不可达。
    • 主要缺点是需要两倍的内存空间。
  3. 标记-整理(Mark-Compact):
    • 先标记可回收的对象,然后将所有存活的对象向一端移动,最后清理掉边界外的所有空间。
    • 解决了标记-清除算法的内存碎片问题。
  4. 分代收集(Generational Collection):
    • 根据对象的生命周期将堆划分为不同的代,如新生代和老年代,不同代采用不同的垃圾回收策略。
    • 新生代通常采用复制算法,而老年代则可能使用标记-整理或标记-清除算法。
  5. 增量式垃圾回收(Incremental GC):
    • 为了减少垃圾回收对应用程序的影响,可以将整个垃圾回收过程分成多个小步进行,每次只处理一部分工作。
  6. 并发/并行垃圾回收(Concurrent/Parallel GC):
    • 并发指的是垃圾回收器与应用程序线程同时运行;并行指的是使用多线程来进行垃圾回收以提高效率。
  7. G1垃圾回收器(Garbage First GC):
    • 是一种服务器端的垃圾回收器,它旨在提供高吞吐量的同时尽量减少停顿时间。
    • G1将整个堆划分成多个大小相等的独立区域(Region),然后根据预计的停顿时间优先回收价值最大的区域。

3.总结安装Nexus步骤实现私有仓库

0)安装环境准备:

复制代码
	4C 8G	JD8
	Nexus版本 3.63

1)安装JDK8

bash 复制代码
[root@nexus: ~]# apt update && apt install -y openjdk-8-jdk
[root@nexus: ~]# java -version
openjdk version "1.8.0_432"
OpenJDK Runtime Environment (build 1.8.0_432-8u432-ga~us1-0ubuntu2~22.04-ga)
OpenJDK 64-Bit Server VM (build 25.432-bga, mixed mode)

2)下载并启动Nexus

bash 复制代码
wget https://download.sonatype.com/nexus/3/nexus-3.63.0-01-unix.tar.gz
tar xvf nexus-3.63.0-01-unix.tar.gz -C /usr/local/
cd /usr/local/
ln -s nexus-3.63.0-01/ nexus
ln -s /usr/local/nexus/bin/nexus /usr/bin/

#指定身份运行
vim /usr/local/nexus/bin/nexus.rc
run_as_user="root"
#查看JVM配置文件
cat /usr/local/nexus/bin/nexus.vmoptions
-Xms2703m
-Xmx2703m

#创建service文件
vim /lib/systemd/system/nexus.service
[Unit]
Description=nexus service
After=network.target

[Service]
Type=forking
LimitNOFILE=65536
ExecStart=/usr/local/nexus/bin/nexus start
ExecStop=/usr/local/nexus/bin/nexus stop
User=root
#User=nexus
Restart=on-abort

[Install]
WantedBy=multi-user.target

#开机启动
systemctl daemon-reload 
systemctl enable --now nexus.service 
systemctl status nexus.service
#验证监听端口
ss -tnl

3)登录web界面初始化

http://10.0.0.205:8081

复制代码
	点右上角Sign in
	提示输入用户名用密码,用户名admin,密码在以下路径查看
	cat /usr/local/sonatype-work/nexus3/admin.password
	登录后更改密码

4)使用 Nexus 构建私有 Apt 仓库

1. 创建Blob Store


2. 创建APT仓库


生成仓库路径:http://10.0.0.205:8081/repository/ubuntu2204-apt/

3. 配置客户端的 Apt 源指向私有仓库路径

客户端:10.0.0.150

cp /etc/apt/sources.list /etc/apt/sources.list.bak

vim /etc/apt/sources.list

4. 测试

在150主机上安装软件 redis-server进行测试,仓库地址已经是私有仓库地址。

查看Nexus Web端仓库的状态

相关推荐
A小辣椒2 天前
TShark:Wireshark CLI 功能
linux
A小辣椒2 天前
TShark:基础知识
linux
AlfredZhao2 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao3 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334663 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪3 天前
linux 拷贝文件或目录到指定的位置
linux
摇滚侠4 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush44 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5204 天前
Linux 11 动态监控指令top
linux
不会C语言的男孩4 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言