Heartbeat基础知识详细总结

栏目: 服务器 · 发布时间: 5年前

内容简介:在日常的集群系统架构中,一般用到Heartbeat的主要就2种:1)高可用(High Availability)HA集群, 使用Heartbeat实现,也称为”双机热备”, “双机互备”, “双机”;2)负载均衡群集(Load Balance Cluster),使用Linux Virtual Server(LVS)实现;

在日常的集群系统架构中,一般用到Heartbeat的主要就2种:

1)高可用(High Availability)HA集群, 使用Heartbeat实现,也称为”双机热备”, “双机互备”, “双机”;

2)负载均衡群集(Load Balance Cluster),使用Linux Virtual Server(LVS)实现;

Heartbeat 的介绍

Heartbeat是Linux-HA项目中的一个组件,它实现了一个高可用集群系统。 心跳服务和集群通信是高可用集群的两个关键组件,在 Heartbeat项目里,由heartbeat模块实现了这两个功能 。Heartbeat是目前开源HA项目中十分成功的一个例子,它提供了所有 HA 软件所需要的基本功能,比如 心跳检测和资源接管、监测群集中的系统服务、在群集中的节点间转移共享 IP 地址的所有者 等,自1999年开始到现在,Heartbeat在行业内得到了广泛的应用。heartbeat最核心的功能包括两个部分,心跳监测和资源接管。心跳监测可以通过网络链路和串口进行,而且支持冗 余链路,它们之间相互发送报文来告诉对方自己当前的状态,如果在指定的时间内未收到对方发送的报文,那么就认为对方失效,这时需启动资源接管模块来接管运行在对方主机上的资源或者服务。

Hearbeat和Keepalived区别

1) Keepalived使用的VRRP协议方式,虚拟路由冗余协议 (Virtual Router Redundancy Protocol,简称VRRP);

2) Heartbeat是基于主机或网络的服务的高可用方式;

3) Keepalived的目的是模拟路由器的双机;

4) Heartbeat的目的是用户Service的双机;

5) LVS的高可用建议用Keepavlived;

6) 业务的高可用用Heartbeat;

Keepalived 主要控制IP飘移,配置应用简单,而且分层,layer3,4,5,各自配置极为简单

Heartbeat 不但可以控制IP飘移,更擅长对资源服务的控制,配置,应用比较复杂;

HA集群中的相关术语

.节点(node)

运行heartbeat进程的一个独立主机,称为节点,节点是HA的核心组成部分,每个节点上运行着操作系统和heartbeat软件服务,在heartbeat集群中,节点有主次之分,分别称为主节点和备用/备份节点,每个节点拥有唯一的主机名,并且拥有属于自己的一组资源,例如,磁盘、文件系统、网络地址和应用服务等。主节点上一般运行着一个或多个应用服务。而备用节点一般处于监控状态。

.资源(resource)

资源是一个节点可以控制的实体,并且当节点发生故障时,这些资源能够被其它节点接管,heartbeat中,可以当做资源的实体有:

-  磁盘分区、文件系统

-  IP地址

-  应用程序服务

-  NFS文件系统

.事件(event)

集群中可能发生的事情,例如节点系统故障、网络连通故障、网卡故障、应用程序故障等。这些事件都会导致节点的资源发生转移,HA的测试也是基于这些事件来进行的。

.动作(action)

事件发生时HA的响应方式,动作是由 shell 脚步控制的,例如当某个节点发生故障后,备份节点将通过事先设定好的执行脚本进行服务关闭或启动, 进而接管故障节点的资源。

HeartBeat 的组成

Heartbeat提供了高可用集群最基本的功能,例如,节点间的内部通信方式、集群合作管理机制、监控 工具 和失效切换功能等等,目前的最新版本是Heartbeat2.x,下面讲述也是以Heartbeat2.x为主,主要介绍Heartbeat2.0的内部组成,主要分为以下几大部分:

heartbeat : 节点间通信检测模块

ha-logd : 集群事件日志服务

CCM (Consensus Cluster Membership):集群成员一致性管理模块

LRM (Local Resource Manager):本地资源管理模块

Stonith Daemon : 使出现问题的节点从集群环境中脱离

CRM (Cluster resource management):集群资源管理模块

Cluster policy engine : 集群策略引擎

Cluster transition engine

:集群转移引擎

下图显示的是Heartbeat2.0内部结构组成

Heartbeat基础知识详细总结

Heartbeat仅仅是个HA软件,它仅能完成心跳监控和资源接管,不会监视它控制的资源或应用程序, 要监控资源和应用程序是否运行正常,必须使用第三方的插件,例如ipfail、Mon、Ldirector等 Heartbeat自身包含了几个插件,分别是ipfail、Stonith和Ldirectord ,介绍如下:

ipfail插件 的功能直接包含在Heartbeat里面,主要用于检测网络故障,并作出合理的反应,为了实现这个功能,ipfail使用ping节点或者ping节点组来检测网络连接是否出现故障,从而及时的做出转移措施。

Stonith 插件 可以在一个没有响应的节点恢复后,合理接管集群服务资源,防止数据冲突,当一个节点失效后,会从集群中删除,如果不使用Stonith插件,那么失效的节点可能会导致集群服务在多于一个节点运行,从而造成数据冲突甚至是系统崩溃。因此,使用Stonith插件可以保证共享存储环境中的数据完整性。

Ldirector插件 是一个监控集群服务节点运行状态的插件。Ldirector如果监控到集群节点中某个服务出现故障,就屏蔽此节点的对外连接功能,同时将后续请求转移到正常的节点提供服务,这个插件经常用在LVS负载均衡集群中,关于Ldirector插件的使用,将在后面详细讲述。

同样,对于操作系统自身出现的问题,Heartbeat也无法监控,如果主节点操作系统挂起,一方面可能导致服务中断,另一方面由于主节点资源无法释放,而备份节点却接管了主节点的资源,此时就 发生了两个节点同时争用一个资源的状况针对这个问题,就需要在 linux 内核中启用一个叫watchdog的模块 ,watchdog是一个Linux内核模块,它通过定时向/dev/watchdog设备文件执行写操作,从而确定系统是否正常运行,如果watchdog认为内核挂起,就会重新启动系统,进而释放节点资源。

在linux中完成watchdog功能的软件叫softdog,softdog维护一个内部计时器,此计时器在一个进程写入/dev/watchdog设备文件时更新,如果softdog没有看到进程写入/dev/watchdog文件,就认为内核可能出了故障。watchdog超时周期默认是一分钟,可以通过将watchdog集成到Heartbeat中,从而通过Heartbeat来监控系统是否正常运行。

HeartBeat 的作用

通过HeartBeat,可以将资源(IP以及程序服务等资源)从一台已经故障的计算机快速转移到另一台正常运转的机器上继续提供服务,一般称之为高可用的服务。在实际的生产应用场景中,heartbeat的功能和另一个高可用的开源软件keepalived有很多的相同之处,在我们实际的生产业务中也是有区别的。

HeartBeat 的工作原理

heartbeat最核心的包括两个部分,心跳监测部分和资源接管部分 ,心跳监测可以通过网络链路和串口进行,而且支持冗 余链路,它们之间相互发送报文来告诉对方自己当前的状态,如果在指定的时间内未收到对方发送的报文,那么就认为对方失效,这时需启动资源接管模块来接管运行在对方主机上的资源或者服务。

Heartbeat: ( 心跳检测)本身是整个集群的基础(cluster messaging layer),负责维护集群各节点的信息以及它们之前通信;只提供主从备份功能,并不能对各个节点进行监控,需要安装ldirectord。

Resource-agent : (资源代理)就是各种的资源的ocf脚本,这些脚本将被LRM调用从而实现各种资源启动、停止、监控等等。

Cluster-glue:  相当于一个中间层,可以将heartbeat和crm(pacemaker)联系起来,主要包含2个部分,LRM和STONITH;

Ldirectord:  负责realserver的健康检查,可以自动将realserver中宕机的机器移除,不再分配请求。

通过修改Heartbeat的软件的配置文件,可以制定那一台Heartbeat服务器作为主服务器,则另一台将自动成为热备服务器。然后在热备服务器上配置Heartbeat守护程序来监听来自主服务器的心跳消息。如果热备服务器在指定时间内为监听到来自主服务器的心跳,就会启动故障转义程序,并取得主服务器上的相关资源服务的所有权,接替主服务器继续不间断的提供服务,从而达到资源以及服务高可用的目的。

以上的描述heartbeat的主备模式,heartbeat还支持主主模式,即两台服务器互为主备,这是他们之间还会互相发送报文来告诉对方自己的当前的状态,如果在指定的时间内未收到对方发送的心跳报文,那么,一方就会认为对方失效或者是已经宕机了,这时每个运行正常的主机就会启动自身的资源接管模块来接管运行在对方主机上的资源或者是服务,继续为用户提供服务。一般情况下,可以较好的实现一台主机故障后,企业业务能够不间断的持续的提供服务 (注意:所谓的业务不间断) 。在故障转移期间也是需要切换时间的,heartbeat的切换时间是5-20秒。 (服务器宕机的切换比人工切换要快 ).

另外,和 keepalived高可用软件一样, heartbeat高可用是操作系统级别的,不是服务(软件)级别的,可以通过简单的脚本控制,实现服务级别的高可用! 

故障切换的常见条件:

1)主机服务器物理宕机(硬件损坏,操作系统故障)

2)Heartbeat服务本身故障

3)两台主备服务器之间的连接线路故障

应用服务故障则不会产生切换,可以通过服务宕机把heartbeat服务停掉。

heartbeat内部结构有三大部分组成

集群成员一致性管理模块(CCM 用于管理集群节点成员,同时管理成员之间的关系和节点间资源的分配,heartbeat模块负责检测主次节点的运行状态,以决定节点是否失效。ha-logd模块用于记录集群中所有模块和服务的运行信息。

本地资源管理器(LRM) 负责本地资源的启动,停止和监控,一般由LRM守护进程lrmd和节点监控进程(Stonith Daemon)组成,lrmd守护进程负责节点间的通信,Stonith Daemon通常是一个Fence设备,主要用于监控节点状态,当一个节点出现问题时处于正常状态的节点会通过Fence设备将其重启或关机以释放IP、磁盘等资源,始终保持资源被一个节点拥有,防止资源争用的发生。

集群资源管理模块(CRM) 用于处理节点和资源之间的依赖关系,同时,管理节点对资源的使用,一般由CRM守护进程crmd、集群策略引擎和集群转移引擎三个部分组成,集群策略引擎(Cluster policy engine)具体实施这些管理和依赖,集群转移引擎(Cluster transition engine)监控CRM模块的状态,当一个节点出现故障时,负责协调另一个节点上的进程进行合理的资源接管。

在Heartbeat集群中, 最核心的是heartbeat模块的心跳监测部分和集群资源管理模块的资源接管部分 ,心跳监测一般由串行接口通过串口线来实现,两个节点之间通过串口线相互发送报文来告诉对方自己当前的状态,如果在指定时间内未收到对方发送的报文,则就认为对方失效,这时资源接管模块将启动,用来接管运行在对方主机上的资源或者服务。

HeartBeat 的心跳连接

高可用集群是指一组通过硬件和软件连接起来的独立计算机,它们在用户面前表现为一个单一系统,在这样的一组计算机系统内部的一个或者多个节点停止工作,服务会从故障节点切换到正常工作的节点上运行,不会引起服务中断。从这个定义可以看出,集群必须检测节点和服务何时失效,何时恢复为可用。这个任务通常由一组被称为“心跳”的代码完成。在Linux-HA里这个功能由一个叫做heartbeat的程序完成。

通过上面的描述,要部署heartbeat服务,至少需要两台主机才能完成。 那么,要实现高可用服务,这两台主机之间,是如何做到互相通信互相监控的呢?

下面是 两台heartbeat主机之间通信的一些常用的可行方法

1)串行电缆,即所谓的串口(首选,缺点是距离不能太远)

2)一根以太网电缆量网口直连(生产环境中常用的方式)

3)以太网电缆,通过交换机等网络设备连接(次选,原因是增加了故障点,不好排查故障,同时线路不是专用的心跳线,容易受其他数据传输的影响,导致心跳报文发送问题)

Heartbeat 的裂脑

什么是裂脑?

由于两台高可用服务器之间在指定的时间内,无法互相检测到对方心跳而各自启动故障转移功能,取得了资源以及服务的所有权,而此时的两台高可用服务器对都还活着并作正常运行,这样就会导致同一个IP湖综合服务在两端同时启动而发生冲突的严重问题,最严重的就是两台主机同时占用一个VIP的地址,当用户写入数据的时候可能会分别写入到两端,这样可能会导致服务器两端的数据不一致或造成数据的丢失,这种情况就本成为裂脑,也有的人称之为分区集群或者大脑垂直分隔!

简单来说, Hearbeat脑裂说的就是 两台服务都正常,但是就是检测不到对方的心跳信息(心跳通信出现故障),两台heartbeat都绑定VIP,这就是脑裂,由于相互失去联系,两台服务器本能的争取接管资源,最严重的后果:共享资源被瓜分,服务都起不起来了,又或者服务都起来,但是共享资源同时写,最后数据就被破坏了!

导致裂脑发生的原因:

一般来说,裂脑的发生,主要是由以下的几个原因导致的:

1)高可用服务器对之间心跳线路故障,导致无法正常的通信。原因比如:

1--心跳线本身就坏了(包括断了,老化);

2--网卡以及相关驱动坏了,IP配置及冲突问题;

3--心跳线间连接的设备故障(交换机的故障或者是网卡的故障);

4--仲裁的服务器出现问题。

2)高可用服务器对上开启了防火墙阻挡了心跳消息的传输;

3)高可用服务器对上的心跳网卡地址等信息配置的不正确,导致发送心跳失败;

4)其他服务配置不当等原因,如心跳的方式不同,心跳广播冲突,软件出现了BUG等。

简单来说,Heartbeat脑裂的原因可能就是:

1) 心跳线断了,无法通讯(老鼠咬了,线材老化);

2) 使用网路直连时,网卡驱动坏了,局域网IP冲突;

3) 心跳线之间的中转设备坏了(仲裁设备坏了);

4) iptables防火墙;

5) 地址信息不对(掩码……),配置丢失;

6) 网线误拔;

防止脑裂发生的方法:

发生脑裂的时候,对业务的影响是及其严重的,有的时候甚至是致命的。

比如:两台高可用的服务器对之间发生脑裂,导致互相竞争同一个IP资源,就如同我们局域网内常见的IP地址冲突一样,两个机器就会有一个或者两个不正常,影响用户正常访问服务器。如果是应用在数据库或者是存储服务这种极重要的高可用上,那就导致用户发布的数据间断的写在两台服务器上的恶果,最终数据恢复及困难或者是难已恢复

实际的生产环境中,我们可以从以下几个方面来防止裂脑的发生:

1)同时使用串行电缆和以太网电缆连接,同时用两条心跳线路,这样一条线路坏了,另一个线路还是好的,依然能传送消息(推荐的)

2)检测到裂脑的时候强行的关闭一个心跳节点(需要特殊的节点支持,如stonith,fence),相当于程序上备节点发现心跳线故障,发送关机命令到主节点。

3)做好对裂脑的监控报警(如邮件以及手机短信等),在问题发生的时候能够人为的介入到仲裁,降低损失。当然,在实施高可用方案的时候,要根据业务的实际需求确定是否能够容忍这样的损失。对于一般的网站业务,这个损失是可控的(公司使用)

4)启用磁盘锁。正在服务一方锁住共享磁盘,脑裂发生的时候,让对方完全抢不走共享的磁盘资源。但使用锁磁盘也会有一个不小的问题,如果占用共享盘的乙方不主动解锁,另一方就永远得不到共享磁盘。现实中介入服务节点突然死机或者崩溃,另一方就永远不可能执行解锁命令。后备节点也就截关不了共享的资源和应用服务。于是有人在HA中涉及了“智能”锁,正在服务的一方只在发现心跳线全部断开时才启用磁盘锁,平时就不上锁了

5)报警报在服务器接管之前,给人员处理留足够的时间就是1分钟内报警了,但是服务器不接管,而是5分钟之后接管,接管的时间较长。数据不会丢失,但就是会导致用户无法写数据。

6)报警后,不直接自动服务器接管,而是由人员接管。

7)增加仲裁的机制,确定谁该获得资源,这里面有几个参考的思路:

1--增加一个仲裁机制。例如设置参考的IP,当心跳完全断开的时候,2个节点各自都ping一下参考的IP,不同则表明断点就出现在本段,这样就主动放弃竞争,让能够ping通参考IP的一端去接管服务。

2--通过第三方软件仲裁谁该获得资源,这个在阿里有类似的软件应用

简单来说,解决Heartbeat脑裂的办法:

1) 做冗余;

2) 做好脑裂监控报警(在仲裁设备上做),仲裁方式停服;

3) 多个仲裁机制(仲裁设备,第三方仲裁软件);

4) 一旦报警,短信电话通知运维人员,服务不要自动接管服务,有人员操作;

HeartBeat 的配置文件

heartbeat主要的配置文件有3个:

1)认证文件authkeys

2)主配置文件ha.cf

3)资源文件haresources

接下来就重点说一下这3个文件的具体功能以及配置:

1)heartbeat的认证配置文件authkeys ,内容如下

auth 1

1 crc

2 sha1 HI!

3 md5 Hello!

该文件主要是用于集群中两个节点的认证,采用的算法和密钥(如果有的话)在集群中节点上必须相同,目前提供了3种算法:md5,sha1和crc。

其中 crc不能够提供认证,它只能够用于校验数据包是否损坏而sha1,md5需要一个密钥来进行认证,从资源消耗的角度来讲,md5消耗的比较多,sha1次之,因此建议一般使用sha1算法

如果要采用sha1算法,只需要将authkeys中的auth 指令(去掉注释符)改为2,而对应的2 sha1行则需要去掉注释符(#),后面的密钥自己改变(两节点上必须相同)。改完之后,保存, 同时需要改变该文件的属性为600,否则heartbeat启动将失败

2)heartbeat的主要配置文件ha.cf

第一个是ha.cf该文件位于在安装后创建的/etc/ha.d目录中。该文件中包括为Heartbeat使用何种介质通路和如何配置他们的信息。在源代码目录中的ha.cf文件包含了您可以使用的全部选项,详述如下:

debugfile /var/log/ha-debug     用于记录heartbeat的调试信息

logfile /var/log/ha-log        用于记录heartbeat的日志信息

如果未定义上述的日志文件,那么日志信息将送往local0(对应的#/var/log/messages),如果这3个日志文件都未定义,那么heartbeat默认情况下

将在/var/log下建立ha-debug和ha-log来记录相应的日志信息。

keepalive 2        发送心跳报文的间隔,默认单位为秒,如果你毫秒为单位,那么需要在后面跟ms单位,如1500ms即代表1.5s

deadtime 30      用于配置认为对方节点菪掉的间隔

warntime 10      发出最后的心跳警告报文的间隔

initdead 120      网络启动的时间

udpport 694       广播/单播通讯使用的udp端口

bcast eth0 Linux      心跳所使用的网络接口

baud 19200      波特率,串口通信的速度。

udpport 694     使用端口694进行bcast和ucast通信。这是默认的,并且在IANA官方注册的端口号。

mcast eth0 225.0.0.1 694 1 0

如果采用组播通讯,在这里可以设置组播通讯所使用的接口,绑定的组播ip地#址(在224.0.0.0 - 239.255.255.255间),通讯端口,ttl(time to live)所能经过路由的#跳数,是否允许环回(也就是本地发出的数据包时候还接收)

ucast eth0 192.168.1.2       如果采用单播,那么可以配置其网络接口以及所使用的ip地址

auto_failback on        该选项是必须配置的!用于决定当拥有该资源的属主恢复之后,资源是否变迁:是迁移到属主上,还是在当前节点上继续运行,直到当前节点出现故障。

stonith baytech /etc/ha.d/conf/stonith.baytech        用于共享资源的集群环境中,采用stonith防御技术来保证数据的一致性

watchdog /dev/watchdog       该指令是用于设置看门狗定时器,如果节点一分钟内都没有心跳,那么节点将重新启动

node ken3      设置集群中的节点,注意:节点名必须与uname –n相匹配

node primary.mydomain.com    该选项是必须配置的。集群中机器的主机名,与“uname –n”的输出相同。

node backup.mydomain.com    该选项是必须配置的。同上。

respawn     该选项是可选配置的:列出将要执行和监控的命令。例如:要执行ccm守护进程,则要添加如下的内容:

ping 10.10.10.254

ping指令以及下面的ping_group指令是用于建立伪集群成员,它们必须与下述#的ipfail指令一起使用,它们的作用是监测物理链路,也就是说如果集群节点与上述伪设备不相通,那么该节点也将无权接管资源或服务,它将释放掉资源。

respawn hacluster /usr/lib/heartbeat/ccm

使得Heartbeat以userid(在本例中为hacluster)的身份来执行该进程并监视该进程的执行情况,如果其死亡便重启之。

对于ipfail,则应该是:

respawn hacluster /usr/lib/heartbeat/ipfail

对于pingd则应该是:

respawn hacluster /usr/lib64/heartbeat/pingd -m 100 -d 5s

注意:如果结束进程的退出代码为100,则不会重启该进程。

apiauth pingd gid=haclient uid=hacluster

apiauth client-name gid=gidlist uid=uidlist

apiauth ipfail gid=haclient uid=hacluster 设置你所指定的启动进程的权限

3)heartbeat的资源配置文件haresources

配置好ha.cf文件之后,便是haresources文件。

该文件列出集群所提供的��务以及服务的默认所有者,该文件主要是为部署的集群配置资源或者服务。

注意:

两个集群节点上的该文件必须相同。集群的IP地址是该选项是必须配置的,不能在haresources文件以外配置该地址, haresources文件用于指定双机系统的主节点、集群IP、子网掩码、广播地址以及启动的服务等。

它的每一有效行的格式如下:

node-name resource1 resource2 ... resourceN

其中node-name即为集群中某一节点的名称,必须与uname –n相同,

后面的资源组resource1 resource2 …resourceN中每一个资源都是一个shell脚本,它们的搜索路径为/etc/init.d/和/usr/local/etc/ha.d/resource.d(该路径根据你所安装heartbeat的路径有所不同),heartbeat为我们提供了一个非常好的资源扩展框架,如果我们需要控制一种自己的资源,只需要实现一个支持start和stop参数的shell脚本就可以了,目前heartbeat所支持的资源脚本可以在我提供的上述路径中去查看。

如下配置进行说明:

node-name network-config

其中node-name指定双机系统的主节点,取值必须匹配ha.cf文件中node选项设置的主机名中的一个,node选项设置的另一个主机名成为从节点。network-config用于网络设置,包括指定集群IP、子网掩码、广播地址等。resource-group用于设置heartbeat启动的服务,该服务最终由双机系统通过集群IP对外提供。在本文中我们假设要配置的HA服务为Apache和Samba。

在haresources文件中需要如下内容:

primary.mydomain.com 192.168.85.3 httpd smb

该行指定在启动时,节点linuxha1得到IP地址192.168.85.3,并启动Apache和Samba。在停止时,Heartbeat将首先停止smb,然后停止Apache,最后释放IP地址192.168.85.3。这里假设命令“uname –n”的输出为“primary.mydomain.com”-如果输出为“primary”,便应使用“primary”。

primary.mydomain.com IPaddr::192.168.21.107/24/eth0 drbddisk::r0 Filesystem::/dev/drbd1::/data::ext4 nfs

正确配置好haresources文件之后,将ha.cf和haresource拷贝到/etc/ha.d目录。

注意:资源文件中能执行的命令必须在/etc/ha.d/resource.d/ 中可见!

Linux公社的RSS地址https://www.linuxidc.com/rssFeed.aspx

本文永久更新链接地址: https://www.linuxidc.com/Linux/2019-01/156140.htm


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

PERL學習手札.

PERL學習手札.

簡信昌 / 上奇科技 / 20040816 / NT$ 390

1. 關於Perl 當你翻開這本書的時候,你也就進入了一個奇幻的世界。Perl確實是一種非常吸引人的程式語言,而之所以這麼引人入勝的原因不單單在於他的功能,也在於他寫作的方式,或說成為一種程式寫作的藝術。即使你只是每天埋首於程式寫作的程式設計師,也不再讓生活過份單調,至少你可以嘗試在程式碼中多一些變化。而且許多Perl的程式設計師已經這麼作了,這也是Perl的理念-「There is mor......一起来看看 《PERL學習手札.》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器