当前位置: 首页 > news >正文

Ceph入门到精通-大流量10GB/s支持OSPF(ECMP)-LVS 集群

Keepalived-LVS 能够提高集群的高可用性并增加后端检测功能、简化配置,满足常规需求。但Keepalived-LVS集群中,同一个VIP只能由一台设备进行宣告,为一主多备的架构,不能横向拓展集群的性能,为此我们引入OSPF来解决该问题。

OSPF(ECMP)

ECMP(Equal-CostMultipathRouting)等价多路径,存在多条不同链路到达同一目的地址的网络环境中,如果使用传统的路由技术,发往该目的地址的数据包只能利用其中的一条链路,其它链路处于备份状态或无效状态,并且在动态路由环境下相互的切换需要一定时间,而等值多路径路由协议可以在该网络环境下同时使用多条链路,不仅增加了传输带宽,并且可以无时延无丢包地备份失效链路的数据传输。

特点:

  1. 基于流的均衡负载
  2. 最大链路数受设备限制(最高16)
  3. 所有链路都active,故障链路自动剔除

LVS+OSPF(ECMP)

利用ECMP以上特性,可以将LVS集群进行横向拓展,利用quagga启ospf
为模拟集群环境,我们准备了六台虚拟机分别为Client、LVS-1、LVS-2、RealServer1、RealServer2、Router,VIP设为192.168.0.100

  • Router :192.168.0.1 192.168.1.1
  • Client :192.168.1.2
  • LVS-1 :192.168.0.2
  • LVS-2 :192.168.0.3
  • RealServer1 :192.168.0.4
  • RealServer2 :192.168.0.5

Router 配置

LVS-1、LVS-2与Router需处于同一ospf域中,通过 IP 192.168.0.1 与LVS1/LVS2/RealServer1/RealServer2 通讯,IP 192.168.1.1 与 Client通讯

[root@router ~]# echo 1 >  /proc/sys/net/ipv4/ip_forward
// 开启转发
[root@router ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 192.168.0.1  netmask 255.255.255.0  broadcast 192.168.0.255inet6 fe80::20c:29ff:fe6e:d10e  prefixlen 64  scopeid 0x20<link>ether 00:0c:29:6e:d1:0e  txqueuelen 1000  (Ethernet)RX packets 63921  bytes 5978914 (5.7 MiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 24354  bytes 2334494 (2.2 MiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0ens38: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 192.168.1.1  netmask 255.255.255.0  broadcast 192.168.1.255inet6 fe80::20c:29ff:fe6e:d122  prefixlen 64  scopeid 0x20<link>ether 00:0c:29:6e:d1:22  txqueuelen 1000  (Ethernet)RX packets 60501  bytes 5206254 (4.9 MiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 18358  bytes 1432690 (1.3 MiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 127.0.0.1  netmask 255.0.0.0inet6 ::1  prefixlen 128  scopeid 0x10<host>loop  txqueuelen 1000  (Local Loopback)RX packets 1119  bytes 88568 (86.4 KiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 1119  bytes 88568 (86.4 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
// ens33:192.168.0.1 与LVS1/LVS2/RealServer1/RealServer同一子网 , ens38:192.168.1.1 与Client同一子网
[root@LVS1 ~]# yum install quagga.x86_64 -y
[root@router ~]# vi /etc/quagga/zebra.conf
hostname Router
password test
enable password test
log file /var/log/quagga/zebra.log
service password-encryption
interface ens33
interface ens38
access-list 1 permit 127.0.0.1
ip prefix-list ANY seq 5 permit 0.0.0.0/0 le 32
route-map ANY deny 10match ip address prefix-list ANY
ip protocol ospf route-map ANY
line vtyaccess-class 1
[root@router ~]# vi /etc/quagga/ospfd.conf
hostname Router
password test
log file /var/log/quagga/ospfd.log
log stdout
log syslog
service password-encryption
interface ens33ip ospf hello-interval 1ip ospf dead-interval 4ip ospf priority 1ip ospf cost 1
router ospfospf router-id 192.168.0.7log-adjacency-changesnetwork 192.168.0.0/24 area 0.0.0.0network 192.168.1.0/24 area 0.0.0.0
access-list 1 permit 127.0.0.1
line vtyaccess-class 1

RealServer 配置

realserver.sh 参考上一章节

[root@RealServer1 ~]# ./realserver.sh start
[root@RealServer1 ~]# ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 192.168.0.4  netmask 255.255.255.0  broadcast 192.168.0.255inet6 fe80::20c:29ff:febd:38da  prefixlen 64  scopeid 0x20<link>ether 00:0c:29:bd:38:da  txqueuelen 1000  (Ethernet)RX packets 48635  bytes 4087456 (3.8 MiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 46101  bytes 5700308 (5.4 MiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 127.0.0.1  netmask 255.0.0.0inet6 ::1  prefixlen 128  scopeid 0x10<host>loop  txqueuelen 1000  (Local Loopback)RX packets 30  bytes 2613 (2.5 KiB)RX errors 0  dropped 0  overruns 0  frame 0TX packets 30  bytes 2613 (2.5 KiB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo:0: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 192.168.0.100  netmask 255.255.255.255loop  txqueuelen 1000  (Local Loopback)

LVS 配置

由于我们使用ospf来实现高可用,不开启keepalived的vrrp功能(LVS2也同样配置),只是用其后端检测功能。
在keepalived-LVS集群的抢占模式下,Master在网卡上挂VIP并进行ARP广播,此时VIP对应的设备是唯一的。
但在OSPF-LVS集群中,Router根据ospf信息通过修改报文的目的mac地址转发到对应的LVS来实现均衡负载,并不根据VIP对应的ARP信息,所以对应的每台LVS将VIP挂在在lo上。

[root@LVS1 ~]# vi /etc/keepalived/keepalived.conf
global_defs {router_id LVS1 #路由器标识script_user rootenable_script_security
}virtual_server 192.168.0.100 80 {delay_loop 5lb_algo wrrlb_kind DRpersistence_timeout 60persistence_granularity 255.255.255.255protocol tcpinhibit_on_failure onha_suspendsorry_server 127.0.0.1 80real_server 192.168.0.4 80 {weight 10HTTP_GET{url{path /status_code 200}connect_port 80connect_timeout 2retry 1delay_before_retry 1}}real_server 192.168.0.5 80 {weight 10HTTP_GET{url{path /status_code 200}connect_port 80connect_timeout 2retry 1delay_before_retry 1}}
}
[root@LVS1 ~]# systemctl reload keepalived
[root@LVS1 ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags-> RemoteAddress:Port           Forward Weight ActiveConn InActConn
TCP  192.168.0.100:80 wrr persistent 60-> 192.168.0.4:80               Route   10     0          0-> 192.168.0.5:80               Route   10     0          0
[root@LVS1 ~]# ifconfig lo:0 192.168.0.100 netmask 255.255.255.255 up
//添加VIP到lo
[root@LVS1 ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet 192.168.0.100/32 scope global lo:0valid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000link/ether 00:0c:29:af:6b:f7 brd ff:ff:ff:ff:ff:ffinet 192.168.0.2/24 brd 192.168.0.255 scope global noprefixroute ens33valid_lft forever preferred_lft foreverinet6 fe80::20c:29ff:feaf:6bf7/64 scope linkvalid_lft forever preferred_lft forever
[root@LVS1 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.0.1     0.0.0.0         UG    100    0        0 ens33
192.168.0.0     0.0.0.0         255.255.255.0   U     100    0        0 ens33

安装quagga并进行配置

[root@LVS1 ~]# yum install quagga.x86_64 -y
[root@LVS1 ~]# vi /etc/quagga/zebra.conf
hostname LVS1
# HOSTNAME改为IP也可以
password test
enable password test
log file /var/log/quagga/zebra.log
#log syslog
service password-encryption
interface ens33
access-list 1 permit 127.0.0.1
ip prefix-list ANY seq 5 permit 0.0.0.0/0 le 32
route-map ANY deny 10match ip address prefix-list ANY
ip protocol ospf route-map ANY
line vtyaccess-class 1
[root@LVS1 ~]# vi /etc/quagga/ospfd.conf
hostname LVS1
password test
log file /var/log/quagga/ospfd.log
log stdout
log syslog
service password-encryption
interface ens33ip ospf hello-interval 1ip ospf dead-interval 4ip ospf priority 0ip ospf cost 1
router ospfospf router-id 192.168.0.2log-adjacency-changesnetwork 192.168.0.2/24 area 0.0.0.0
access-list 1 permit 127.0.0.1
line vtyaccess-class 1
[root@LVS1 ~]# systemctl  start zebra
[root@LVS1 ~]# systemctl  start ospfd

同理我们配置完LVS2后进行检测ospf状态

[root@LVS1 ~]# vtysh
Hello, this is Quagga (version 0.99.22.4).
Copyright 1996-2005 Kunihiro Ishiguro, et al.
LVS1# show ip ospf  neighborNeighbor ID Pri State           Dead Time Address         Interface            RXmtL RqstL DBsmL
192.168.0.7       1 Full/DR            3.817s 192.168.0.1     ens33:192.168.0.2        0     0     0
192.168.0.3       0 2-Way/DROther      3.518s 192.168.0.3     ens33:192.168.0.2        0     0     0
LVS1# show ip ospf  route
============ OSPF network routing table ============
N    192.168.0.0/24        [1] area: 0.0.0.0directly attached to ens33
N    192.168.0.100/32      [1] area: 0.0.0.0directly attached to lo
N    192.168.1.0/24        [2] area: 0.0.0.0via 192.168.0.1, ens33============ OSPF router routing table ========================= OSPF external routing table ===========

在Route上查看路由

router# show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,O - OSPF, I - IS-IS, B - BGP, A - Babel,> - selected route, * - FIB routeK>* 0.0.0.0/0 via 192.168.0.10, ens33
C>* 127.0.0.0/8 is directly connected, lo
O   192.168.0.0/24 [110/1] is directly connected, ens33, 00:11:04
C>* 192.168.0.0/24 is directly connected, ens33
O   192.168.0.100/32 [110/2] via 192.168.0.2, ens33 inactive, 00:00:11via 192.168.0.3, ens33 inactive, 00:00:11
O   192.168.1.0/24 [110/1] is directly connected, ens38, 00:12:19
C>* 192.168.1.0/24 is directly connected, ens38
//可以看到 到 192.168.0.100/32 的下一跳分配到 192.168.0.2、192.168.0.3

Client 测试

[root@Client ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    100    0        0 ens33
192.168.1.0     0.0.0.0         255.255.255.0   U     100    0        0 ens33
[root@Client ~]# traceroute 192.168.0.100
traceroute to 192.168.0.100 (192.168.0.100), 30 hops max, 60 byte packets1  192.168.1.1 (192.168.1.1)  0.575 ms  0.258 ms  0.478 ms2  192.168.0.100 (192.168.0.100)  1.901 ms  1.746 ms  1.370 ms
[root@Client ~]# curl 192.168.0.100
RealServer1 192.168.0.4

自动化

以上是最基础的ospf-Lvs集群配置,在实际生产环境中会有自动化部署、监控、告警等需求,例如quagga的初始化配置

quagga 配置

HOSTNAME=`hostname`
PASSWORD=shenyangchangkuan
#获取默认路由对应网卡
NIC=`/sbin/route -n|awk '$1=="default"||$1=="0.0.0.0"{print $NF}'|head -n 1`
if [ -z $NIC ];thenecho "get NIC err,NIC is null!"
fi
#获取该网卡IP
#centos7改为下面这行
#IP=`/sbin/ifconfig $NIC |grep "inet "|sed 's/:/ /'|awk '{print $2}'`
IP=`/sbin/ifconfig $NIC|grep "inet addr"|sed 's/:/ /'|awk '{print $3}'`
if  [ -z $IP ];thenecho "get IP err,IP is null!"exit 1
fi#将该网卡及子网卡IP信息写入tmp/lvs_network.tmp
echo "">/tmp/lvs_network.tmp
for cfg in ` ls -l  /etc/sysconfig/network-scripts/ifcfg-${NIC}*|awk '{print $NF}'`
docat $cfg |grep IPADDR=|awk -F "=" '{print $2}' |sed 's/"//g'>>/tmp/lvs_network.tmp
done

相关文章:

Ceph入门到精通-大流量10GB/s支持OSPF(ECMP)-LVS 集群

Keepalived-LVS 能够提高集群的高可用性并增加后端检测功能、简化配置&#xff0c;满足常规需求。但Keepalived-LVS集群中&#xff0c;同一个VIP只能由一台设备进行宣告&#xff0c;为一主多备的架构&#xff0c;不能横向拓展集群的性能&#xff0c;为此我们引入OSPF来解决该问…...

IDEA、git如何修改历史提交commit的邮箱

第一种情况&#xff1a;当前提交不是从其他分支clone过来的&#xff1a; step1&#xff1a; git log 查看提交日志&#xff0c;获取commit ID step2&#xff1a; git rebase -i [你的commitID] git rebase -i c2ef237854290051bdcdb50ffbdbb78481d254bb step3&#xff1a;…...

字符设备驱动(内核态用户态内存交互)

前言 内核驱动&#xff1a;运行在内核态的动态模块&#xff0c;遵循内核模块框架接口&#xff0c;更倾向于插件。 应用程序&#xff1a;运行在用户态的进程。 应用程序与内核驱动交互通过既定接口&#xff0c;内核态和用户态访问依然遵循内核既定接口。 环境搭建 系统&#…...

Qt基础 线程池

目录 QThreadPool类 QRunnable类 应用场景示例 QThreadPool类 主要属性&#xff1a; 1、activeThreadCount: 此属性表示线程池中的活动线程数&#xff0c;通过activeThreadCount() 调用。 2、expiryTimeout: 线程活着的时间。没有设置expiryTimeout毫秒的线程会自动退出&am…...

Django(8)-静态资源引用CSS和图片

除了服务端生成的 HTML 以外&#xff0c;网络应用通常需要一些额外的文件——比如图片&#xff0c;脚本和样式表——来帮助渲染网络页面。在 Django 中&#xff0c;我们把这些文件统称为“静态文件”。 我们使用static文件来存放静态资源&#xff0c;django会在每个 INSTALLED…...

C++ list模拟实现

list模拟实现代码&#xff1a; namespace djx {template<class T>struct list_node{T _data;list_node<T>* _prev;list_node<T>* _next;list_node(const T& x T()):_data(x),_prev(nullptr),_next(nullptr){}};template<class T,class Ref,class Pt…...

中国建筑出版传媒许少辉博士八一新书乡村振兴战略下传统村落文化旅游设计日京东当当畅销榜自由营九三学

中国建筑出版传媒许少辉博士八一新书乡村振兴战略下传统村落文化旅游设计日京东当当畅销榜自由营九三学...

C语言(第三十二天)

1. 递归是什么&#xff1f; 递归是学习C语言函数绕不开的一个话题&#xff0c;那什么是递归呢&#xff1f; 递归其实是一种解决问题的方法&#xff0c;在C语言中&#xff0c;递归就是函数自己调用自己。 写一个史上最简单的C语言递归代码&#xff1a; #include <stdio.h>…...

arcgis+postgresql+postgis使用介绍

关于arcgis在postgresql创建地理数据库我分享一下自己的经历&#xff1a; 众所周知&#xff0c;arcgis如果在oracle中创建地理数据库&#xff0c;必须要使用ArcToolbox里面的地理数据库工具去创建&#xff0c;在里面发现它还可以创建sql_server, postgresql数据库类型&#xf…...

机器视觉之开运算和闭运算

开运算&#xff08;Opening&#xff09;和闭运算&#xff08;Closing&#xff09;是数学形态学中常用的图像处理操作&#xff0c;通常用于去除图像中的噪声、连接物体、分离物体等操作。它们分别由两个基本操作组成&#xff1a;腐蚀&#xff08;Erosion&#xff09;和膨胀&…...

【python爬虫】—URL管理器的实现

python爬虫-url管理器 url管理器的作用python实现 url管理器的作用 在Python爬虫中&#xff0c;URL管理器&#xff08;URL Manager&#xff09;是一个重要的组件&#xff0c;用于有效管理爬取过程中所涉及的URL。它主要负责以下几个方面的任务&#xff1a; URL去重&#xff08;…...

Oracle 19C RAC安装PSU oui-patch.xml权限错误

Oracle 19C RAC安装PSU时&#xff0c;节点2安装失败&#xff0c;经排查错误原因为oui-patch.xml文件权限错误。 Oracle官方建议oui-patch.xml文件权限&#xff0c;改成660或者666&#xff1a; chmod 660 oui-patch.xml权限修改完成后&#xff0c;安装psu还是失败&#xff0c;…...

华为数通方向HCIP-DataCom H12-821题库(单选题:161-180)

第161题 以下关于 URPF(Unicast Reverse Path Forwarding) 的描述&#xff0c; 正确的是哪一项 A、部署了严格模式的 URPF&#xff0c;也能够可以同时部署允许匹配缺省路由模式 B、如果部署松散模式的 URPF&#xff0c;默认情况下不需要匹配明细路由 C、如果部署松散模式的…...

ResNet详解:网络结构解读与PyTorch实现教程

目录 一、深度残差网络&#xff08;Deep Residual Networks&#xff09;简介深度学习与网络深度的挑战残差学习的提出为什么ResNet有效&#xff1f; 二、深度学习与梯度消失问题梯度消失问题定义为什么会出现梯度消失&#xff1f;激活函数初始化方法网络深度 如何解决梯度消失问…...

ChatGPT 随机动态可视化图表分析

动态可视化图表分析实例如下图: 这样的动态可视化图表可以使用ChatGPT OpenAI 来实现。 给ChatGPT发送指令: 你现在是一个数据分析师,请使用HTML,JS,Echarts,来完成一个动态条形图,条形图方向横向,数据可以随机生成,并且随机生成10个不同的商品名称,每个类别分别用…...

国标视频融合云平台EasyCVR视频汇聚平台的应用场景及其功能说明

一、平台简介 EasyCVR国标视频融合云平台是一款基于端-边-云一体化架构的视频融合AI智能分析网关平台。EasyCVR平台支持视频汇聚、融合管理&#xff0c;兼容多类型设备、多协议接入。其提供的视频功能包括&#xff1a;视频监控、无插件直播录像、云存储、检索回放、智能告警、…...

后端面试话术集锦第三篇:spring cloud 面试话术

🚗后端面试集锦目录 💖后端面试话术集锦第 1 篇:spring面试话术💖 💖后端面试话术集锦第 2 篇:spring boot面试话术💖 💖后端面试话术集锦第 3 篇:spring cloud面试话术💖 💖后端面试话术集锦第 4 篇:ElasticSearch面试话术💖 💖后端面试话术集锦第 5 …...

React 18 选择 State 结构

参考文章 选择 State 结构 构建良好的 state 可以让组件变得易于修改和调试&#xff0c;而不会经常出错。以下是在构建 state 时应该考虑的一些建议。 构建 state 的原则 当编写一个存有 state 的组件时&#xff0c;需要选择使用多少个 state 变量以及它们都是怎样的数据格…...

LNMT与动静分离

目录 一、LNMT 一、部署tomcat 二、部署nginx 三、部署mariadb 四、配置nginx 二、操作流程及步骤 一、在第一台机器上进入 vim /etc/nginx/nginx.conf 更改配置文件 二、并查看端口是否成功启动 三、验证 四、再次来到网页验证 五、动静分离&#xff08;修改配置…...

【java】LinkedList 和 ArrayList的简介与对比

Java LinkedList和 ArrayList 在使用上&#xff0c;几乎是一样的。由于LinkedList是基于双向链表的&#xff0c;会多出list.getFirst();获取头部元素等方法 链表&#xff08;Linked list&#xff09;是一种常见的基础数据结构&#xff0c;是一种线性表&#xff0c;但是并不会按…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中&#xff0c;从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备&#xff08;如专用硬件设备&#xff09;&#xff0c;从而消除了直接物理连接的需要。USB over IP的…...

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...

Linux nano命令的基本使用

参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时&#xff0c;显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...