博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[连载型] Neutron系列(20):Neutron L3 Agent HA 之 虚拟路由冗余协议(VRRP)【下】...
阅读量:4656 次
发布时间:2019-06-09

本文共 14077 字,大约阅读时间需要 46 分钟。

问题导读:

1.HA Router如何高度?
2.Juno VRRP 实现需要注意什么?
3.Neutron Kilo 新版本都有什么?
2.2 HA Router 调度(scheduling)

Neutron L3 Agent 的调度包括三个层面:
 
  • 普通(Legacy)L3 Agent 调度:在存在多个 L3 Agent 的时候,通过随机或者最小 router 数算法找到一个 L3 Agent,将该 Router 部署在上面。
  • 分布式(DVR)L3 Agent 调度:将 Router 分布到所有计算节点和网络节点。
  • 高可用(HA) L3 Agent 调度:见下文

 

    关于 HA L3 Agent 的调度,这部分的实现代码在 这里。新的代码修改了已有的 scheduler 算法,使得它们可以支持 HA Router,但是目前不能同时支持 DVR 和 HA Router。主要代码在 /n eutron/scheduler/l3_agent_scheduler.py。该实现在 Neutron server 配置文件中添加了如下的配置项:

 

[AppleScript] 
纯文本查看 复制代码
1
2
3
4
neutron.conf
:
l
3
_ha
=
True
#由管理做的全局配置,创建的所有 router 均为 HA Router
max_l
3
_agents_per_router
=
4
#每个 HA router 最多被部署到若干个 L3 Agent 上
min_l
3
_agents_per_router
=
2
#每个 HA Router 最少被部署到若干个 L3 Agent 上

该文件:
 
(1)检查可用的 L3 Agent 数目(candidates)是否超过 conf.min_l3_agents_per_router 。
 
(2)确定部署的 router 数目,取 min(candidates,conf.max_l3_agents_per_router )。
 
(3)实现两个 scheduler 类:ChanceScheduler - 随机地在可用的 L3 Agent 上部署 Router;LeastRoutersScheduler - 将 router 部署到所管理的 router 数目最少的 L3 Agent 上。它们根据不同的算法选出待部署 router 实例的 L3 Agent。
 
(4)bind_router 函数会执行 db 操作,将 router 和 scheduler 选出的 L3 Agent 绑定在一起。比如:
 
[AppleScript] 
纯文本查看 复制代码
1
2
2015
-08
-01
10
:
42
:
21.4
88
19430
DEBUG neutron.scheduler.l
3
_agent_scheduler [req
-827
c
863
f
-
cb
01
-4650
-
a
26
d
-0
f
176
ef
84026
None] HA Router
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
is
scheduled
to
L
3
agent
04
c
360
d
0
-3066
-4
f
04
-9
af
2
-
d
4
ef
8586
ad
2
b
)
bind_ha_router_to_agents
/
usr
/
lib
/
python
2.7
/
dist
-
packages
/
neutron
/
scheduler
/
l
3
_agent_scheduler.py
:
330
2015
-08
-01
10
:
42
:
21.5
47
19430
DEBUG neutron.scheduler.l
3
_agent_scheduler [req
-827
c
863
f
-
cb
01
-4650
-
a
26
d
-0
f
176
ef
84026
None] Router
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
is
scheduled
to
L
3
agent
4705
d
27
c
-5008
-4828
-
b
619
-
bbb
2114188
ba bind_router
/
usr
/
lib
/
python
2.7
/
dist
-
packages
/
neutron
/
scheduler
/
l
3
_agent_scheduler.py
:
226

当确定的部署数量为2 时,会是下面的情形:
 
<ignore_js_op>

2.3 Keepalived notifier script ( VRRP 状态变化时的通知脚本)

Neutron 的 KeepalivedNotifierMixin 类实现了 keepalived 在 VRRP 状态变化时的通知方法。Neturon 添加了 VRRP 状态变为 master,backup 和 fault 状态时的 notifier。
 
  • 变更为 master 状态时的 notifier script:

 

[AppleScript] 
纯文本查看 复制代码
1
2
3
#!/usr/bin/env bash
neutron
-
ns
-
metadata
-
proxy
--pid_file=/var/lib/neutron/external/pids/04f6e792-3b79-4b8f-a577-2ad38d33a2bb.pid --metadata_proxy_socket=/var/lib/neutron/metadata_proxy --router_id=04f6e792-3b79-4b8f-a577-2ad38d33a2bb --state_path=/var/lib/neutron --metadata_port=9697 --debug --verbose --log-file=neutron-ns-metadata-proxy-04f6e792-3b79-4b8f-a577-2ad38d33a2bb.log --log-dir=/var/log/neutron
echo
-
n master
>
/
var
/
lib
/
neutron
/
ha_confs
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
/
state

第一个命令,在 router network namespace 中启动 neutron-ns-metadata-proxy,这样使用该 router 的虚机就可以通过该 proxy 访问 metadata service 了。关于 metadata service, proxy 和 agent,可以参考文章 (1)(2)(3)。

 

第二个命令,设置 state 文件内容为 “master”。 Keepalived 不支持直接查询 VRRP 状态,因此,只能通过 state 变化时被调用的脚本文件来保存其状态。
 
  • 变更为 backup 状态的 notifier script:

 

[AppleScript] 
纯文本查看 复制代码
1
2
3
#!/usr/bin/env bash
kill
-9
$
(
cat
/
var
/
lib
/
neutron
/
external
/
pids
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb.pid
)
echo
-
n backup
>
/
var
/
lib
/
neutron
/
ha_confs
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
/
state

第一个命令,在 router network namespace 中杀掉 neutron-ns-metadata-proxy 进程,这样使用该 router 的虚机就无法通过该 proxy 访问 metadata service 了。
 
第二个命令,在 state 文件中记录 VRRP state 为 “backup”。
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
#!/usr/bin/env bash
kill
-9
$
(
cat
/
var
/
lib
/
neutron
/
external
/
pids
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb.pid
)
echo
-
n fault
>
/
var
/
lib
/
neutron
/
ha_confs
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
/
state

因此,第一次 VRRP 选举完成后,即有一个 Master router 被选举出来。这时候,各节点上不同的 script 会执行不同的动作:
 
  • Master router 的节点上:启动 route namespace 对应的 neutron-ns-metadata-proxy 进程,保存 “master” 至 state 文件,设置 VIP(包括配置文件中 virtual ipaddress 指定的 IP 地址和 virtual_ipaddress_excluded 部分的 IP 地址)和 virtual_routes 部分的 route。
  • Slave router 的节点上:杀掉 route namespace 对应的 neutron-ns-metadata-proxy 进程,保存 “backup” 至 state 文件,清除 VIP 和 virtual_routes 部分的 route。

2.4 依次添加 gateway,subnet,虚机 和 浮动 IP

    这些操作都是对已有 HA router 的更新。 当 HA Router 的信息发生改变的时候,执行 DB 操作后,Neutron Server 会通知部署有 router 实例的 L3 Agent,然后它会去获取到更新后的信息,重新生成新的 keepalived 配置文件,然后通知 keepalived 去使用新的配置文件。
 

2.4.1 添加 gateway

    keepalived 的配置文件的 virtual_ipaddress_excluded 部分会增加 gateway 的 interface IP:192.168.1.113/24 dev qg-f19f97bc-e5 作为一个 VIP。这个 VIP 地址会在 Master node 被设置,在 Backup node 上不会被设置。
 
master:
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
4
36
:
qg
-
f
19
f
97
bc
-
e
5
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
14
:
be
:
06
brd ff
:
ff
:
ff
:
ff
:
ff
:
ff
    
inet
192.1
68.1
.
113
/
24
scope
global
qg
-
f
19
f
97
bc
-
e
5
       
valid_lft forever preferred_lft forever

slave:
 
[AppleScript] 
纯文本查看 复制代码
1
2
61
:
qg
-
f
19
f
97
bc
-
e
5
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
14
:
be
:
06
brd ff
:
ff
:
ff
:
ff
:
ff
:
ff

2.4.2 添加 subnet interface

    同样地,keepalived 的配置文件的 virtual_ipaddress_excluded 部分会增加 subnet的 gateway IP:10.0.10.1/24 dev qr-73641a84-72 做为一个新的 VIP。这个 VIP 会在 Master node 被设置,在 Backup node 上不会被设置。
 
master:
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
4
37
:
qr
-73641
a
84
-72
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
86
:
dd
:
53
brd ff
:
ff
:
ff
:
ff
:
ff
:
ff
    
inet
10.0
.
10.1
/
24
scope
global
qr
-73641
a
84
-72
       
valid_lft forever preferred_lft forever

bakckup:
 
[AppleScript] 
纯文本查看 复制代码
1
2
62
:
qr
-73641
a
84
-72
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
86
:
dd
:
53
brd ff
:
ff
:
ff
:
ff
:
ff
:
ff

2.4.3 添加一个虚机到 10.0.10.1/24 网络

    虚机的默认网关为 10.0.10.1,这正是 Master node 上的 qr-73641a84-72 interface 上设置的 VIP 。因此,虚机发送到不是本机所在网络的网络包都会经过本 interface 进入 Master 路由器。
 

2.4.4 向该 IP 添加一个 浮动 IP 192.168.1.112

    同样地,keepalived 的配置文件的 virtual_ipaddress_excluded 部分会增加该 浮动 IP 和它所在的 external port:192.168.1.112/32 dev qg-f19f97bc-e5 作为一个新的 VIP。这个 VIP 会在 Master node 被设置,在 Backup node 上不会被设置。
 
该 VIP 被加到了 Master router 的 external port 上:
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
4
5
6
36
:
qg
-
f
19
f
97
bc
-
e
5
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
14
:
be
:
06
brd ff
:
ff
:
ff
:
ff
:
ff
:
ff
    
inet
192.1
68.1
.
113
/
24
scope
global
qg
-
f
19
f
97
bc
-
e
5
       
valid_lft forever preferred_lft forever
    
inet
192.1
68.1
.
112
/
32
scope
global
qg
-
f
19
f
97
bc
-
e
5
       
valid_lft forever preferred_lft forever

同样,在 Slave router 的 exernal port 上没有添加。
 
但是,每一次 router 实例都更新的时候,Master router 和 Backup router 的 iptables 规则保持了一致的更新。 从以上过程可以看出,在某一时刻,只有 Master router 的 interface 在接受虚机发来的网络包,其它 VRRP router 只是在 standby。
 
至此,Master 和 Backup L3 Agent namespace 的效果为:
 
<ignore_js_op>

2.5 HA Router 故障切换

  非抢占模式下,会触发 keepalived  VRRP failover 的情况包括:
 
  • 当 slave 节点在规定的时间内没有收到 master 的心跳:比如 一个 L3 Agent 上的 keepalived 进程死了,或者 HA Device down 了,或者 HA network down 了等。除此以外的其它情况,都需要使用 workaround 来触发故障切换:比如使用 peacemaker 监视 L3 Agent,一旦发现它 down 了,立刻将 HA Device down 掉。
  • 当 master 节点上的 externa gateway 在规定的时间内无法访问时:这里有个 bug报出来了,到目前为止还没有被解决。
    为了验证 failover,把 master node 上的  HA Device down 掉。
 
[AppleScript] 
纯文本查看 复制代码
1
ip netns exec qrouter
-04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb ifconfig ha
-20894
a
79
-
b
6
down

 

这时候,该节点的 VRRP 状态变为 fault。
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
4
5
6
Aug 
1
15
:
26
:
58
network Keepalived_vrrp[
4415
]
:
Kernel
is
reporting
:
interface ha
-20894
a
79
-
b
6
DOWN
Aug 
1
15
:
26
:
58
network Keepalived_vrrp[
4415
]
:
Kernel
is
reporting
:
interface ha
-20894
a
79
-
b
6
DOWN
Aug 
1
15
:
26
:
58
network Keepalived_vrrp[
4415
]
:
VRRP_Instance
(
VR_
1
)
Entering FAULT STATE
Aug 
1
15
:
26
:
58
network Keepalived_vrrp[
4415
]
:
VRRP_Instance
(
VR_
1
)
Now
in
FAULT
state
Aug 
1
15
:
26
:
58
network Keepalived_vrrp[
4415
]
:
VRRP_Group
(
VG_
1
)
Syncing instances
to
FAULT
state
Aug 
1
15
:
26
:
58
network Keepalived_vrrp[
4415
]
:
Opening
script
file
/
var
/
lib
/
neutron
/
ha_confs
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
/
notify_fault.sh

    原 backup node 上的 keepalived 因为在规定时间内收不到 VRRP 通告,主动发起选举过程,将自己变为 Master 状态,触发 notify_master.sh 被调用。这时候,该节点上的 router namespace 的 qr,gg 和 ha interface 的 VIP 全部被配置了,而且 route 规则也增加了。它已经接替原 master 节点向虚机提供路由服务。

 

[AppleScript] 
纯文本查看 复制代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
60
:
ha
-
a
8
a
3
a
49
f
-
c
1
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
84
:
24
:
7
f brd ff
:
ff
:
ff
:
ff
:
ff
:
ff
    
inet
169.2
54.1
92.1
/
18
brd
169.2
54.2
55.2
55
scope
global
ha
-
a
8
a
3
a
49
f
-
c
1
       
valid_lft forever preferred_lft forever
    
inet
169.2
54.0
.
1
/
24
scope
global
ha
-
a
8
a
3
a
49
f
-
c
1
       
valid_lft forever preferred_lft forever
    
inet
6
fe
80
:
:
f
816
:
3
eff
:
fe
84
:
247
f
/
64
scope link
       
valid_lft forever preferred_lft forever
61
:
qg
-
f
19
f
97
bc
-
e
5
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
14
:
be
:
06
brd ff
:
ff
:
ff
:
ff
:
ff
:
ff
    
inet
192.1
68.1
.
112
/
32
scope
global
qg
-
f
19
f
97
bc
-
e
5
       
valid_lft forever preferred_lft forever
    
inet
192.1
68.1
.
113
/
24
scope
global
qg
-
f
19
f
97
bc
-
e
5
       
valid_lft forever preferred_lft forever
    
inet
6
fe
80
:
:
f
816
:
3
eff
:
fe
14
:
be
06
/
64
scope link
       
valid_lft forever preferred_lft forever
62
:
qr
-73641
a
84
-72
:
<
BROADCAST
,
UP
,
LOWER_UP
>
mtu
1500
qdisc noqueue
state
UNKNOWN
group
default
    
link
/
ether fa
:
16
:
3
e
:
86
:
dd
:
53
brd ff
:
ff
:
ff
:
ff
:
ff
:
ff
    
inet
10.0
.
10.1
/
24
scope
global
qr
-73641
a
84
-72
       
valid_lft forever preferred_lft forever
    
inet
6
fe
80
:
:
f
816
:
3
eff
:
fe
86
:
dd
53
/
64
scope link
       
valid_lft forever preferred_lft forever

 

[AppleScript] 
纯文本查看 复制代码
1
2
3
4
5
6
7
8
root@network
:
/
home
/
s
1
# ip netns exec qrouter-04f6e792-3b79-4b8f-a577-2ad38d33a2bb route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0
.
0.0        
192.1
68.1
.
1    
0.0
.
0.0        
UG   
0     
0       
0
qg
-
f
19
f
97
bc
-
e
5
10.0
.
10.0      
0.0
.
0.0        
255.2
55.2
55.0  
U    
0     
0       
0
qr
-73641
a
84
-72
169.2
54.0
.
0    
0.0
.
0.0        
255.2
55.2
55.0  
U    
0     
0       
0
ha
-20894
a
79
-
b
6
169.2
54.1
92.0  
0.0
.
0.0        
255.2
55.1
92.0  
U    
0     
0       
0
ha
-20894
a
79
-
b
6
192.1
68.1
.
0    
0.0
.
0.0        
255.2
55.2
55.0  
U    
0     
0       
0
qg
-
f
19
f
97
bc
-
e
5

从外网 ping 虚机看, failover 过程中,网络有若干秒的中断,而且有建立起来的连接断了:
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
4
64
bytes
from
192.1
68.1
.
112
:
icmp_seq
=
41
ttl
=
63
time
=
2.5
3
ms
64
bytes
from
192.1
68.1
.
112
:
icmp_seq
=
42
ttl
=
63
time
=
2.2
3
ms
64
bytes
from
192.1
68.1
.
112
:
icmp_seq
=
50
ttl
=
63
time
=
5.3
5
ms
64
bytes
from
192.1
68.1
.
112
:
icmp_seq
=
51
ttl
=
63
time
=
2.1
1
ms

这个问题会在后续版本会使用 conntrackd 来解决。   
 
在 HA Device 重新 UP 后,VRRP 状态从  fault 变为 Backup 并一直保持该状态:
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
4
5
Aug 
1
15
:
39
:
37
network Keepalived_vrrp[
4415
]
:
Kernel
is
reporting
:
Group
(
VG_
1
)
UP
Aug 
1
15
:
39
:
37
network Keepalived_vrrp[
4415
]
:
VRRP_Group
(
VG_
1
)
Leaving FAULT
state
Aug 
1
15
:
39
:
37
network Keepalived_vrrp[
4415
]
:
VRRP_Instance
(
VR_
1
)
Entering BACKUP STATE
Aug 
1
15
:
39
:
37
network Keepalived_vrrp[
4415
]
:
VRRP_Group
(
VG_
1
)
Syncing instances
to
BACKUP
state
Aug 
1
15
:
39
:
37
network Keepalived_vrrp[
4415
]
:
Opening
script
file
/
var
/
lib
/
neutron
/
ha_confs
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
/
notify_backup.sh

所有 port 的 VIP 和 route 规则都被删除了。
 
再将 master namespace 上的 HA Device down 掉,backup namespace 中的 keepalive 重新变为 Master:
 
[AppleScript] 
纯文本查看 复制代码
1
2
3
4
Aug 
1
15
:
41
:
58
network Keepalived_vrrp[
4415
]
:
VRRP_Instance
(
VR_
1
)
Transition
to
MASTER STATE
Aug 
1
15
:
41
:
58
network Keepalived_vrrp[
4415
]
:
VRRP_Group
(
VG_
1
)
Syncing instances
to
MASTER
state
Aug 
1
15
:
41
:
58
network Keepalived_vrrp[
4415
]
:
Opening
script
file
/
var
/
lib
/
neutron
/
ha_confs
/
04
f
6
e
792
-3
b
79
-4
b
8
f
-
a
577
-2
ad
38
d
33
a
2
bb
/
notify_master.sh
Aug 
1
15
:
42
:
00
network Keepalived_vrrp[
4415
]
:
VRRP_Instance
(
VR_
1
)
Entering MASTER STATE

所有 port 的 VIP 和 route 规则都被设置了。
 

3. Juno VRRP 小结和后续版本的改进

3.1 Juno VRRP 实现小结

  • Juno VRRP 使用 Keepalived,在每个 HA Route 的实例的 namespace 中启动一个 keepalived 进程,它采用非抢占式模式。
  • keepalived 进程只监控 HA Device,在其不可用时触发选举机制。
  • neutron 依赖 keepalived 设置或者清除 VIP (包括 VRRP VIP 和浮动 IP,internal/external port IP)
  • neutron 依赖 keepalived 设置或者清除 virtual_routes 部分的 route 规则
  • neutron 在 keepalived VRRP 状态变化时保存 VRRP 的状态到本地文件
  • 所有 HA Route 实例的 namespace 中,只有 master namespace 提供 port 上的 IP 实际向网络内的虚机提供路由服务。neutron 依赖 keepalived 在 failover 时发送无用 ARP 来更新指定网络内机器的 ARP 表。
  • Juno 版本中的实现还不完善,比如只能监控 HA Device,不能监控别的 port,包括 internal 和 external 端口,以及 external link 等;还未实现切换时保留 TCP 连接的状态。

3.2 后续版本中的持续改进

    Juno 版本中增加 VRRP 的实现实现后,有很多地方需要改进,有大量的 blueprint 被开出来,但是大都进展缓慢。比较有意思的有几个:
 
  • 这个 blueprint增加 conntracked 来支持 keepalived failover 后保存已建立的 TCP 连接。目前还没完成。
  • 通过监视  HA Device 的  ip 来监视 keepalived 节点的状态
  • 这个 blueprint增加 neutron API 来 report keepalived master。已合并到 M 版本。
  • 这个 blueprint 同时支持 DVR 和 HR,但是还未开工。
  • 这个 bug打算增加 checker 来监视 external gateway。未完成。

 

这也能看出,Neutron 在基础部分(L2,L3)的实现比较扎实,但是在高级功能的实现上,包括 VRRP,DVR,VPN/FW/LBaas 等,还是不够扎实,想应用到生成环境中还需要做大量的工作。
 

4. Kilo 版本更新 (//2015/11/27 更新)

Neutron Kilo 版本中,新增了 neutron l3-agent-list-hosting-router <router_id> 命令来查看 master l3-agent 在哪个网络节点上。

 

<ignore_js_op>

 

[AppleScript] 
纯文本查看 复制代码
1
2
3
4
5
6
root@hkg
023
:
~
# neutron l3-agent-list-hosting-router 03cb51be-3558-4253-8062-db177679e141
+
--------------------------------------+-------------------+----------------+-------+----------+
|
id                                  
| host              | admin_state_up | alive | ha_state |
+
--------------------------------------+-------------------+----------------+-------+----------+
|
39
b
13
aea
-45
a
9
-4336
-
afb
4
-
c
555
b
488
e
92
d | hkg
02
kvm          | True           |
:
-
)  
|          |
+
--------------------------------------+-------------------+----------------+-------+----------+

转载于:https://www.cnblogs.com/liuhongru/p/11098406.html

你可能感兴趣的文章
文件读写方式的对比
查看>>
Ecplise快捷键
查看>>
又一年过去了
查看>>
sgu175---pascal
查看>>
HDU-5536 Chip Factory (字典树)
查看>>
重点错误记录
查看>>
IDEA kotlin 配置
查看>>
关于es6中let的相关问题
查看>>
vue学习:props,scope,slot,ref,is,slot,sync等知识点
查看>>
sass判断语句
查看>>
MYSQL查看当前正在使用的数据库命令
查看>>
Java通过MouseInfo获取鼠标位置
查看>>
win10升级至专业版
查看>>
SpringBoot入门篇--整合mybatis+generator自动生成代码+druid连接池+PageHelper分页插件+SpringBoot整合Mybatis-plus...
查看>>
秒杀系统架构分析与实战
查看>>
大数据概述
查看>>
windbg cs
查看>>
maven配置【转载】
查看>>
洛谷—— P1080 国王游戏
查看>>
Django框架介绍
查看>>