第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端仓库的状态

相关推荐
BUG 4045 分钟前
LINUX--shell
linux·运维·服务器
菜鸟小白:长岛icetea11 分钟前
Linux零基础速成篇一(理论+实操)
linux·运维·服务器
深海的鲸同学 luvi13 分钟前
【HarmonyOS NEXT】hdc环境变量配置
linux·windows·harmonyos
dowhileprogramming1 小时前
Python 中的迭代器
linux·数据库·python
过过过呀Glik1 小时前
在 Ubuntu 服务器上添加和删除用户
linux·服务器·ubuntu
Tesseract_95273 小时前
ioctl回顾
linux
Java小白中的菜鸟3 小时前
centos7的磁盘扩容
linux·运维·服务器
黑子哥呢?5 小时前
Linux---防火墙端口设置(firewalld)
linux·服务器·网络
F-2H6 小时前
C语言:指针4(常量指针和指针常量及动态内存分配)
java·linux·c语言·开发语言·前端·c++
aherhuo6 小时前
基于openEuler22.09部署OpenStack Yoga云平台(一)
linux·运维·服务器·openstack