Kubernetes——Debug Static Pod

news2024/11/23 21:28:41

1. 问题背景

注意,我这里的Static Pod并非KubernetesStatic Pod,而是需要把想要Debug的程序放到Delve环境中重新打包一个镜像。因为还有另外一种场景,那就是我们需要不重启Running Pod,为了和这种方式区分,才以此为名。

最近遇到一个问题,简单说明一下背景。

由于虚拟机重新启动,造成Redis Operator无法组建Redis集群,报错为:[ERR] Node 10.233.75.71:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0

这个错误比较典型,在网上一搜索就能找到解决方案。其实就是因为虚拟机重新启动之后,Pod被重建,IP发生变动,而nodes.conf文件由于被持久化,因此里面记录了上一次集群的信息。因此解决的方案也很简单,就是删除aof/rdb/nodes.conf文件。详细可以参考这篇文章:Operator——Redis之重启虚拟机后无法重建集群

为了让Redis Operator能够自动处理这种情况,我修改了Redis Operator的源码,如果在组件集群的时候发现是上面所说的错误,就自动删除aof/rdb/nodes.conf文件,重建集群

程序改完之后,发现Redis Operator一直卡在某个地方,实际上根据Redis Operator的源码可以知道,就算RedisCluster资源不发生改动,Redis Operator也会每隔10s重新Reconcile一遍。即便遇到错误返回,也会在120s之后,重新Reconcile

{"level":"info","ts":1671086466.020392,"logger":"controllers.RedisCluster","msg":"Will reconcile redis cluster operator in again 10 seconds","Request.Namespace":"redis-system","Request.Name":"redis"}
{"level":"info","ts":1671086476.0212002,"logger":"controllers.RedisCluster","msg":"Reconciling opstree redis Cluster controller","Request.Namespace":"redis-system","Request.Name":"redis"}
{"level":"info","ts":1671086476.0256453,"logger":"controller_redis","msg":"Redis statefulset get action was successful","Request.StatefulSet.Namespace":"redis-system","Request.StatefulSet.Name":"redis-leader"}
{"level":"info","ts":1671086476.0356286,"logger":"controller_redis","msg":"Reconciliation Complete, no Changes required.","Request.StatefulSet.Namespace":"redis-system","Request.StatefulSet.Name":"redis-leader"}
{"level":"info","ts":1671086476.0390885,"logger":"controller_redis","msg":"Redis service get action is successful","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-leader-headless"}
{"level":"info","ts":1671086476.0410442,"logger":"controller_redis","msg":"Redis service is already in-sync","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-leader-headless"}
{"level":"info","ts":1671086476.0445807,"logger":"controller_redis","msg":"Redis service get action is successful","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-leader"}
{"level":"info","ts":1671086476.0464318,"logger":"controller_redis","msg":"Redis service is already in-sync","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-leader"}
{"level":"info","ts":1671086476.0476692,"logger":"controller_redis","msg":"Redis PodDisruptionBudget get action failed","Request.PodDisruptionBudget.Namespace":"redis-system","Request.PodDisruptionBudget.Name":"redis-leader"}
{"level":"info","ts":1671086476.047689,"logger":"controller_redis","msg":"Reconciliation Successful, no PodDisruptionBudget Found.","Request.PodDisruptionBudget.Namespace":"redis-system","Request.PodDisruptionBudget.Name":"redis-leader"}
{"level":"info","ts":1671086476.0511396,"logger":"controller_redis","msg":"Redis statefulset get action was successful","Request.StatefulSet.Namespace":"redis-system","Request.StatefulSet.Name":"redis-leader"}
{"level":"info","ts":1671086476.05468,"logger":"controller_redis","msg":"Redis statefulset get action was successful","Request.StatefulSet.Namespace":"redis-system","Request.StatefulSet.Name":"redis-follower"}
{"level":"info","ts":1671086476.0869293,"logger":"controller_redis","msg":"Reconciliation Complete, no Changes required.","Request.StatefulSet.Namespace":"redis-system","Request.StatefulSet.Name":"redis-follower"}
{"level":"info","ts":1671086476.0903852,"logger":"controller_redis","msg":"Redis service get action is successful","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-follower-headless"}
{"level":"info","ts":1671086476.0920627,"logger":"controller_redis","msg":"Redis service is already in-sync","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-follower-headless"}
{"level":"info","ts":1671086476.0965445,"logger":"controller_redis","msg":"Redis service get action is successful","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-follower"}
{"level":"info","ts":1671086476.0986211,"logger":"controller_redis","msg":"Redis service is already in-sync","Request.Service.Namespace":"redis-system","Request.Service.Name":"redis-follower"}
{"level":"info","ts":1671086476.099773,"logger":"controller_redis","msg":"Redis PodDisruptionBudget get action failed","Request.PodDisruptionBudget.Namespace":"redis-system","Request.PodDisruptionBudget.Name":"redis-follower"}
{"level":"info","ts":1671086476.0997992,"logger":"controller_redis","msg":"Reconciliation Successful, no PodDisruptionBudget Found.","Request.PodDisruptionBudget.Namespace":"redis-system","Request.PodDisruptionBudget.Name":"redis-follower"}
{"level":"info","ts":1671086476.1040905,"logger":"controller_redis","msg":"Redis statefulset get action was successful","Request.StatefulSet.Namespace":"redis-system","Request.StatefulSet.Name":"redis-follower"}
{"level":"info","ts":1671086476.104127,"logger":"controllers.RedisCluster","msg":"Creating redis cluster by executing cluster creation commands","Request.Namespace":"redis-system","Request.Name":"redis","Leaders.Ready":"3","Followers.Ready":"3"}
{"level":"info","ts":1671086476.1103818,"logger":"controller_redis","msg":"Successfully got the ip for redis","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis-leader-0","ip":"10.233.74.86"}
{"level":"info","ts":1671086476.1114752,"logger":"controller_redis","msg":"Redis cluster nodes are listed","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis","Output":"cf0291a193357d03c6c2e6a67cf012689840affe 10.233.74.86:6379@16379 myself,master - 0 1671078114882 1 connected\n"}
{"level":"info","ts":1671086476.1115515,"logger":"controller_redis","msg":"Total number of redis nodes are","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis","Nodes":"1"}
{"level":"info","ts":1671086476.1184812,"logger":"controller_redis","msg":"Successfully got the ip for redis","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis-leader-0","ip":"10.233.74.86"}
{"level":"info","ts":1671086476.1197286,"logger":"controller_redis","msg":"Redis cluster nodes are listed","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis","Output":"cf0291a193357d03c6c2e6a67cf012689840affe 10.233.74.86:6379@16379 myself,master - 0 1671078114882 1 connected\n"}
{"level":"info","ts":1671086476.1197934,"logger":"controller_redis","msg":"Number of redis nodes are","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis","Nodes":"1","Type":"leader"}
{"level":"info","ts":1671086476.1198037,"logger":"controllers.RedisCluster","msg":"Not all leader are part of the cluster...","Request.Namespace":"redis-system","Request.Name":"redis","Leaders.Count":1,"Instance.Size":3}
{"level":"info","ts":1671086476.1235414,"logger":"controller_redis","msg":"Successfully got the ip for redis","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis-leader-0","ip":"10.233.74.86"}
{"level":"info","ts":1671086476.1272135,"logger":"controller_redis","msg":"Successfully got the ip for redis","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis-leader-1","ip":"10.233.97.165"}
{"level":"info","ts":1671086476.1303189,"logger":"controller_redis","msg":"Successfully got the ip for redis","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis-leader-2","ip":"10.233.75.68"}
{"level":"info","ts":1671086476.130354,"logger":"controller_redis","msg":"Redis Add Slots command for single node cluster is","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis","Command":["redis-cli","--cluster","create","10.233.74.86:6379","10.233.97.165:6379","10.233.75.68:6379","--cluster-yes"]}
{"level":"info","ts":1671086476.133076,"logger":"controller_redis","msg":"Redis cluster creation command is","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis","Command":["redis-cli","--cluster","create","10.233.74.86:6379","10.233.97.165:6379","10.233.75.68:6379","--cluster-yes","-a","T1XmQh9U"]}
{"level":"info","ts":1671086476.1361492,"logger":"controller_redis","msg":"Pod Counted successfully","Request.RedisManager.Namespace":"redis-system","Request.RedisManager.Name":"redis","Count":0,"Container Name":"redis-leader"}
root@lvs-229:~# date +'%Y-%m-%d %H:%M:%S' -d "@1671086476.1361492"
2022-12-15 14:41:16
root@lvs-229:~#

可以看到,程序最后一次输出的日志为20分钟以前,非常的诡异。程序停留在了Pod Counted successfully附近,而我排查了一下源代码,并没有发现阻塞的地方。那么是什么原因导致程序开启了是”卡住“呢?由于redis集群组件的特性,我本地的windows10电脑无法复现,需要在K8S集群只能,Redis Operator才能跑起来。所以我需要能够在K8S PodDebug我修改之后的Redis Operator程序。

2. 编译源码

由于需要Debug源码,而golang编译器默认开启了内联优化,因此我们需要在编译二进制的时候,关闭内联优化

go build -gcflags=all="-N -l" -o manager ./cmd/operator/main.go

如上,通过加入-N -l选项,就可以禁止内联优化

3. Dockerfile

可以Debug的二进制程序准备好了,下面我们就可以准备Dockerfile,上传镜像了,需要注意的是,我们需要在启动的时候通过delve来启动,才能让我们的IDEA连接到Pod当中

FROM golang:1.19.4

MAINTAINER skyguard-bigdata
WORKDIR /
USER root
COPY manager .
RUN chmod +x /manager

RUN go env -w GO111MODULE=on && \
    go env -w GOPROXY=https://goproxy.cn,direct && \
    go install github.com/go-delve/delve/cmd/dlv@latest

EXPOSE 12345

CMD dlv --listen=:12345 --headless=true --api-version=2 --accept-multiclient exec manager -- --leader-elect

构建镜像,如下:

[root@9a394601b73f redis-operator]# docker build -t redis-operator:0.13.2-debug -f Dockerfile-Debug .
Sending build context to Docker daemon  188.4MB
Step 1/9 : FROM golang:1.19.4
 ---> 180567aa84db
Step 2/9 : MAINTAINER skyguard-bigdata
 ---> Using cache
 ---> 5750b24ad20d
Step 3/9 : WORKDIR /
 ---> Using cache
 ---> 1c31e39cec1d
Step 4/9 : USER root
 ---> Using cache
 ---> a059bffdeaf7
Step 5/9 : COPY manager .
 ---> Using cache
 ---> fec9465515d8
Step 6/9 : RUN chmod +x /manager
 ---> Using cache
 ---> 19e9cabec7f7
Step 7/9 : RUN go env -w GO111MODULE=on &&     go env -w GOPROXY=https://goproxy.cn,direct &&     go install github.com/go-delve/delve/cmd/dlv@latest
 ---> Running in 5dfa25abd876
go: downloading github.com/go-delve/delve v1.20.1
go: downloading github.com/sirupsen/logrus v1.6.0
go: downloading github.com/spf13/cobra v1.1.3
go: downloading gopkg.in/yaml.v2 v2.4.0
go: downloading github.com/mattn/go-isatty v0.0.3
go: downloading github.com/cosiner/argv v0.1.0
go: downloading github.com/derekparker/trie v0.0.0-20200317170641-1fdf38b7b0e9
go: downloading github.com/go-delve/liner v1.2.3-0.20220127212407-d32d89dd2a5d
go: downloading github.com/google/go-dap v0.6.0
go: downloading go.starlark.net v0.0.0-20220816155156-cfacd8902214
go: downloading golang.org/x/sys v0.0.0-20220908164124-27713097b956
go: downloading github.com/hashicorp/golang-lru v0.5.4
go: downloading golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4
go: downloading github.com/cpuguy83/go-md2man/v2 v2.0.0
go: downloading github.com/spf13/pflag v1.0.5
go: downloading github.com/mattn/go-runewidth v0.0.13
go: downloading github.com/cilium/ebpf v0.7.0
go: downloading github.com/russross/blackfriday/v2 v2.0.1
go: downloading github.com/rivo/uniseg v0.2.0
go: downloading github.com/shurcooL/sanitized_anchor_name v1.0.0
Removing intermediate container 5dfa25abd876
 ---> 0397bab71dd9
Step 8/9 : EXPOSE 12345
 ---> Running in 3e585f70d0a6
Removing intermediate container 3e585f70d0a6
 ---> 3dd708e29767
Step 9/9 : CMD dlv --listen=:12345 --headless=true --api-version=2 --accept-multiclient exec manager
 ---> Running in 0d8181e63ea7
Removing intermediate container 0d8181e63ea7
 ---> 77f30b173d34
Successfully built 77f30b173d34
Successfully tagged redis-operator:0.13.2-debug
[root@9a394601b73f redis-operator]# docker images
REPOSITORY                          TAG              IMAGE ID       CREATED          SIZE
redis-operator                      0.13.2-debug     77f30b173d34   10 seconds ago   1.21GB

把镜像推送到仓库当中即可

4. Service

由于之前的Redis Operator并不需要提供服务,因此并没有Service,这里我们需要把12345端口暴露出来

注意:如果小伙伴们可以直接访问K8S集群的话,那么这里可以直接使用NodePort的方式暴露端口,并且Apisix那个步骤可以跳过

kind: Service
apiVersion: v1
metadata:
  name: redis-operator-debug
  namespace: redis-system
spec:
  type: ClusterIP
  ports:
    - name: delve
      port: 12345
      targetPort: 12345
  selector:
    control-plane: redis-operator
root@lvs-229:~# kubectl get svc -n redis-system
NAME                      TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)             AGE
redis-follower            ClusterIP   10.233.5.220   <none>        6379/TCP,9121/TCP   28h
redis-follower-headless   ClusterIP   None           <none>        6379/TCP            28h
redis-leader              ClusterIP   10.233.0.234   <none>        6379/TCP,9121/TCP   28h
redis-leader-headless     ClusterIP   None           <none>        6379/TCP            28h
redis-operator-debug      ClusterIP   10.233.19.68   <none>        12345/TCP           19s
root@lvs-229:~#

5. Apisix

由于我们的K8S是通过Apisix网关暴露给外部的,因此这里还需要给Apisix添加一个四层代理,这样外部才能的delve才能连接上K8S内部的Pod

PUT {{ApisixManagerAddr}}/apisix/admin/stream_routes/redis-operator-debug
Content-Type: {{ContentType}}
X-API-KEY: {{ApisixKey}}

{
  "server_port": 9107,
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "10.233.19.68:12345": 1
    }
  }
}

由于集群内的DNS解析暂时有点问题,这里我们通过Service IP找到服务

6. Deployment

修改Redis OperatorImage属性,改为我们前面上传的镜像并且加上特权,privileged: true

切记,这里一定要记得给容器加上特权,否则Debug会有问题

securityContext:
  privileged: true
root@lvs-229:~# kubectl logs -f --tail 100 -n redis-system redis-operator-546fdc76b7-lqz9b
2022-12-15T08:23:44Z error layer=debugger could not create config directory: mkdir .config: permission denied
2022-12-15T08:23:44Z warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
API server listening at: [::]:12345


更新Deployment之后,等待Kubernetes重启好新的Pod,查看日志,发现这个Pod正在等待delve连接进来,接下来,我们启动IDEA

7. IDEA

注意:需要提前打好端点,不然IEDA已启动,很有可能我们需要Debug的地方已经跳过了

在这里插入图片描述

搞定,之后就可以愉快的Debug

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/91144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

彻底卸载并重装Anaconda环境与Python的方法

本文介绍在Windows平台下&#xff0c;彻底删除Anaconda环境与其自带Python版本&#xff0c;并进行重新安装的方法。 最近&#xff0c;由于原有Anaconda环境中的部分第三方库出现了冲突的情况&#xff0c;且基于“Anaconda Prompt (anaconda3)”也无法升级Anaconda与相关库了&am…

《超新星纪元》

《超新星纪元》 关于作者 刘慈欣&#xff0c;髙级工程师&#xff0c;科普作家&#xff0c;被誉 为"中国当代科幻第一人"。自上世纪90年代开始&#xff0c;他一边在发电厂担任计算机工程师&#xff0c;一边利用业余时间出版了13本小说集&#xff0c;连续数年获得中国…

这是一篇讲解用户行为分析的推荐书单和总结

写在前面 技术文延迟了 本来计划参加活动的还有一篇&#xff0c;应该是一篇技术翻译文&#xff0c;但是那篇文章太难了&#xff0c;看我过我以往文章的同学&#xff0c;应该能理解&#xff0c;我的文章很少有3000字数以下的&#xff0c;而且如果不是来自谷歌&#xff08;主要…

深蓝学院-多传感器融合定位课程-第9章-基于图优化的建图方法

专栏文章: 深蓝学院-多传感器融合定位课程-第1章-概述_goldqiu的博客-CSDN博客 深蓝学院-多传感器融合定位课程-第2章-3D激光里程计I_goldqiu的博客-CSDN博客 深蓝学院-多传感器融合定位课程-第3章-3D激光里程计II_goldqiu的博客-CSDN博客 深蓝学院-多传感器融合定位课程-第…

2022品牌出海:日本网红营销白皮书

日本作为世界第三大经济体&#xff0c;同时也是世界第四大电子商务市场&#xff0c;亚洲第二大消费市场&#xff0c;其经济水平和消费能力都非常出色。对出海企业来说&#xff0c;日本是一个非常有吸引力的市场。日本的网红营销市场也非常成熟&#xff0c;在疫情的影响下&#…

java设计模式之原型模式(prototype Pattern)

原型模式主要在于对象的克隆&#xff0c;所以也叫克隆模式 其实就是利用java中的Object对象中的clone方法实现一个对象的克隆。此方法需要注意的是&#xff0c;一个对象想要实现克隆&#xff0c;就必须实现一个标志性接口Cloneable 现在先来说一下浅克隆 这玩意也叫表皮克隆&…

【前端开发学习】1.前端引入和HTML标签

文章目录1.快速开发网站2. 浏览器能识别的标签2.1 编码&#xff08;head&#xff09;2.2 Title&#xff08;head&#xff09;2.3 标题&#xff08;body&#xff09;2.4 div 和 span&#xff08;body&#xff09;2.5 超链接&#xff08;body&#xff09;2.6 图片&#xff08;bod…

基于微信小程序的居民疫情服务系统springboot框架-计算机毕业设计

项目介绍 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;居民疫情服务系统小程序被用户普遍使用&#xff0c;为…

一个基于.Net开发齐全的加密库

网络安全&#xff0c;对于我们项目日常开发&#xff0c;是非常重要的&#xff0c;比如密码加密存储、密码加密传输、SSL证书、端对端加密等等。 这些加密算法&#xff0c;每个知识点都包含了很多内容&#xff0c;自己实现都需要花费很多时间&#xff0c;所以今天就给大家推荐一…

Qt 模型视图编程之增删行列

背景 Qt 模型视图编程中模型定义了标准接口对数据进行访问&#xff0c;可根据需求继承对应的抽象模型类来实现自定义的数据模型。一个基本的数据模型至少要实现以下虚函数&#xff1a; ①&#xff0e;rowCount&#xff1a;行数&#xff0c;返回要显示多少行&#xff1b; ②&…

net基于asp.net的社区团购网站-计算机毕业设计

项目介绍 社区团购系统依托社区团购系统和社区门店,是现在的一个重大市场和发展方向,通过研究企业在社区团购系统环境下的营销模式创新,对于普通的零售业和传统社区团购系统的转型发展具有重要的理论意义。随着互联网行业的发展,人们的生活方式发生着重大变化,人们越来越倾向于…

[附源码]Python计算机毕业设计Django酒店客房管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[附源码]Nodejs计算机毕业设计基于大学生兼职系统Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

前端基础(七)_表单的基本组成与使用

表单 表单&#xff1a;用于采集不同类型的用户输入数据&#xff0c;发送给服务器&#xff0c;实现用户和服务器之间的数据交互&#xff1b; 表单标签 form 用于声明表单&#xff0c;定义数据的采集范围 注意&#xff1a; 1、一个页面中可以有多个表单标签&#xff0c;但是标…

STM32F4 | 串行通信基本原理 | 串口通信实验

文章目录一、串行通信基本原理1.串行通信接口背景知识2.异步串口通信UART知识3.STM32串口数据格式和通信过程4.STM32串口框图5.波特率计算方法二、STM32F429 串口简介三、硬件设计四、软件设计五、实验现象六、STM32CubeMX 配置串口本章介绍如何使用 STM32F429 的串口来发送和…

手把手教你Spring Cloud Alibaba教程:nacos安装

我们在学习springCloud的时候用的注册中心是Eureka: springBoot集成springCloud&#xff08;一&#xff09;注册中心 但是由于houlai Eureka2.0后续不维护&#xff0c;国内就需要一个可靠的注册中心。但是换了一套后&#xff0c;有哪些不同呢 SpringCloud和SpringCloudAliba…

fl21怎么换主题flstudio皮肤怎么换?

FLstudio21如何更改皮肤主题&#xff1f;不光是背景&#xff0c;还有按键什么的&#xff1f; 请参考下面的步骤进行设置fl视图设置。 第1步&#xff0c;打开visualstudiofl视图设置。 第2步fl视图设置&#xff0c;打开“工具”--“选项” 第3步&#xff0c;在“环境”--“常…

基于SpringBoot+MySql的分页功能实现

分页功能是为了缓解数据库的压力而实现的功能,实际上是将数据库中的数据分段查询出来,避免一次性将所有的数据全部查出来,查出来的部分数据通过前端的页面中不同的页数来展现出来 实现基础 mysql数据库中的查询语句中提供的limit关键字 该关键字可以限制查询的记录数,例如 s…

【026】基于vue+springboot的教务信息管理系统(含源码、数据库、课设报告、运行教程)

文章目录一、项目介绍二、源码获取一、项目介绍 基于Vue&#xff0b;springbootmysql的教务信息管理系统&#xff0c;UI设计主要采用element-ui&#xff0c;也使用了echarts做学生成绩的可视化界面&#xff0c;使用了xlsx表导入、导出数据&#xff0c;超级吊的教务管理系统&…

[操作系统笔记]页面置换算法

内容系听课复习所做笔记&#xff0c;图例多来自课程截图 常见的页面置换算法有&#xff1a;最优算法、随机算法、FIFO、LRU 随机算法顾名思义 FIFO(先进先出, First In First Out)算法&#xff1a;可能产生抖动现象和Belady现象 LRU&#xff08;最近最少使用算法&#xff09…