双机热备软件PanguHA图文教程

双机热备软件PanguHA图文教程
双机热备软件PanguHA图文教程

​ 简介

PanguHA是Windows平台的双机热备集群系统,是提供系统高可用性的纯软件解决方案,一般由两个节点构成,分为活动节点及备用节点。通常把正在执行业务的称为活动节点,而作为活动节点的一个备份的则称为备用节点。当活动节点出现问题,导致正在运行的业务不能正常运行时,备用节点此时就会侦测到,并立即接续活动节点来执行业务。从而实现业务的不中断或短暂中断。

运行环境

  • 环境 .NET Framework 4.6.1 及以上

软件安装

无需安装,解压后,点击 HA.exe 运行

功能介绍

  • IP漂移

IP漂移的作用是实现Web应用、WebApi/Webservice、数据库等的故障转移,除了服务器本机的IP地址外,该软件可以对服务器额外设置一个虚拟IP,然后使用虚拟IP作为代理来访问Web应用或数据库,当双机热备配置完成后,虚拟IP挂载于主节点,当主节点宕机以后,该虚拟IP会漂移到备节点继续提供服务,对客户端来说,这个切换是没有感知的,因为它们还是使用虚拟IP作为代理访问。

主节点出现以下情况将进行IP漂移:

  1. 宕机
  2. 网卡异常
  3. Web服务Url异常(需要配置)
  4. Windows服务异常(需要配置)

那么该如何操作呢,我们先选一台服务器A作为主节点,在该节点上打开软件,切换到【IP漂移】标签页,然后选择网络适配器(请确保该网卡设置的是静态IP而非自动获取),如下图所示,

选择网络适配器

目前只支持对一块网卡做虚拟IP,选一个你需要做虚拟IP的那个网段的网卡,然后设置本机IP(假设IP为192.168.56.101)和集群IP(也就是虚拟IP,假设为192.168.56.103,路由器不可设置该IP与Mac绑定),如下图所示,这里需要注意,虚拟IP要和本机IP在同一网段,并且无机器在使用

配置浮动ip

然后添加对方IP,如下图所示,

配置对方IP

然后点击运行,右下角显示失败重试无需管它,等待稍许时间,可发现左下角显示主节点,这个时候就表明主节点设置成功,虚拟IP已经挂载在当前节点,可通过ipconfig命令查看,对方节点红色是因为对方节点还没运行热备软件,如下图所示

对方节点未运行热备软件

心跳间隔和断联重试设置可以调整主备切换的速度,但也不宜设置得过小,否则会因为一点点网络抖动而切换,频繁切换不是一件好事。【切换】按钮提供了手动切换主备的功能。【停止】按钮将停止心跳检测,不进行主备切换。

配置对方IP后,检测对方热备软件在线情况,异常时发送邮件提醒,防火墙需要开放ICMP和默认端口9999,需要注意使用telnet命令检测时请在两端打开PanguHA软件 如果发现端口已开,软件已开,但是telnet不通,需要检查防火墙是否把HA应用给禁掉了,如下图所示

防火墙

对方IP颜色对应的含义

  1. 绿色:正常
  2. 红色:断联
  3. 灰色:不监测

正常情况如下图所示

检测到对方节点健康

添加本机Url可以对本机的Web服务进行检测,如果发现Web服务的状态码不是200的时候,即服务出现异常时(30s内重试3次),如果在主节点上,则进行切换并邮件提醒。如果在备节点上,则进行邮件提醒(防止主节点服务异常没有可用的备节点)。如下图所示

配置Url检测

配置windows服务后,主节点发现Windows服务异常会先进行重启(30s内重试3次),重启失败则进行故障转移。如果是备节点,重启失败发送邮件提醒,如下图所示

配置windows服务检测

接着我们来设置备节点服务器B,假设IP为192.168.56.102,大部分操作都和上面类似,我讲一下需要注意的点,首先两台服务器要能互相ping通,然后两边的集群IP设置是相同的,两台服务器处在同一网段,如下图所示

备节点配置浮动ip

至此,IP漂移设置告一段落,然后我们来测试一下,我们将主节点服务器关闭,观察备节点是否升级为主节点,也就是虚拟IP是否漂移过来,如下图所示,

备节点升级为主节点

可以发现,B服务器从备节点变成了主节点,这个时候访问代理IP将会访问B服务器节点,这样就完成了故障转移的功能。

那么该如何设置Web应用呢,如果使用的是IIS,那么先在两台服务器上部署相同的应用,然后将两边的绑定IP都设置为虚拟IP,如下图所示

web应用设置浮动ip

其他Tomcat等web服务器也是类似的道理,如果绑定虚拟IP导致服务启动失败,绑定0.0.0.0即可。

  • 执行管理

执行管理功能是在IP漂移的基础上,对可执行文件exe或Windows服务做切换配置,配置的进程和windows服务只会在主节点上运行,备节点将会关闭配置的进程和windows服务

那么该如何操作呢,假设我们已经配置完成了IP漂移,然后我们要控制WindowsFormsApp1.exe这个程序的切换,我们只要在A,B两台服务器上都对这个程序进行配置即可,如下图所示,

可执行文件切换

可以看到,配置的进程会在主节点上运行(不小心手动关闭了也会自动启动),在备节点上关闭(不小心启动了也会自动关闭),当主节点A宕机后,备节点B升级为主节点,就会将配置的进程自动开启,这样就实现了进程的切换,windows服务也是同样的配置方法。

  • 文件同步

注意事项:该功能谨慎使用于数据库文件的同步!

文件同步功能是在IP漂移功能基础上进行的,因为该软件的定位并非单纯地做文件同步,而是作为文件服务器来使用的,所以也要搭配虚拟IP来使用。在配置之前需要先设置共享文件夹,如下图所示,

设置共享文件夹

保证IP路径可以访问,即A可以访问B的文件夹IP路径,B可以访问A的文件夹IP路径,如下图所示

IP路径可访问

然后我们将软件切换到【文件同步标签页】,在A服务器上做A->B的同步设置,如下图所示

配置文件同步任务

在B服务器上做B->A的同步设置,如下图所示

备节点配置文件同步任务

然后两边都点击启动,虽然两边都配置了同步路径并启动,但同步任务只会在主节点上运行,当主节点A宕机,备节点B升级为主节点,然后会开启同步任务。文件同步是实时的,右上角的镜像周期是为了防止备节点不小心修改、删除文件,是为了保持备节点的文件始终和主节点一模一样,并非指同步文件需要5分钟延迟。

  • Mysql同步(基于数据库)

部署之前请确保两个节点结构和数据完全一致

详见视频教程:

软件可以快速地部署Mysql双主复制,配合IP漂移功能,即可搭建Mysql高可用架构。那么该如何操作呢,我们将软件切换到【Mysql主从】,根据上面的文字提醒,先在A,B两台服务器做相应配置,如下图所示

mysql配置文件

然后A,B都重启Mysql服务。

然后在A服务器输入相关信息做A主B从的设置,然后点击部署按钮,如下图所示,右下角会提示部署成功,

配置A主B从

接着在B服务器上输入相关信息做B主A从的设置,与上面类似,点击部署按钮,有如下成功提示,如下图所示

配置B主A从

至此,Mysql双主复制搭建完成,除此之外需要保证mysql.user表内有%账号,这样才能保证虚拟IP可以访问mysql。结合IP漂移功能,可以做服务器级别宕机的双机切换,即主节点A服务器宕机后,备节点B升级为主节点,虚拟IP指向B节点,继续提供mysql服务。

如果在下面填写本机Mysql服务名称并开启健康检测,则可以做数据库应用级别的宕机切换,即主节点A的mysql服务挂了,则备节点B可以检测到,然后做虚拟IP的转移,B升级为主节点,继续提供mysql服务。同时,如果备节点的mysql服务挂了,则会发送邮件提醒。如下图所示

主节点Mysql主从检测
备节点主从检测
  • Mysql/Sqlserver/PostgreSQL数据同步(基于软件)

使用须知:同步机制采用订阅发布合并复制,合并复制要求表拥有主键(复合主键也行),并且会增加辅助字段,所以在业务系统中Insert语句需要指定字段(辅助字段无需指定)。

详见视频教程:

Sqlserver清空备节点数据脚本:

 -- 设置目标数据库名称
Use B;
DECLARE @DatabaseName NVARCHAR(128) = N'B';

-- 验证数据库是否存在
IF NOT EXISTS (SELECT 1 FROM sys.databases WHERE name = @DatabaseName)
BEGIN
    RAISERROR(N'错误:数据库 "%s" 不存在!', 16, 1, @DatabaseName);
    RETURN;
END;

-- 声明变量
DECLARE @SchemaName    NVARCHAR(128),
        @TableName     NVARCHAR(128),
        @FullTableName  NVARCHAR(255),
        @SqlStatement  NVARCHAR(MAX);

-- 创建游标获取所有用户表
DECLARE tableCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT 
    s.name AS SchemaName,
    t.name AS TableName
FROM 
    sys.databases db
INNER JOIN 
    sys.tables t ON db.name = @DatabaseName
INNER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    db.name = @DatabaseName 
    AND t.type = 'U';  -- 只获取用户表

-- 开始处理
OPEN tableCursor;

FETCH NEXT FROM tableCursor INTO @SchemaName, @TableName;

WHILE @@FETCH_STATUS = 0
BEGIN
    BEGIN TRY
        -- 构造完整表名和SQL语句
        SET @FullTableName = QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName);
        SET @SqlStatement = N'USE ' + QUOTENAME(@DatabaseName) + N'; 
        TRUNCATE TABLE ' + @FullTableName;

        -- 执行截断操作
        EXEC sp_executesql @SqlStatement;
        PRINT N'成功截断表: ' + @FullTableName;
    END TRY
    BEGIN CATCH
        PRINT N'错误截断表: ' + @FullTableName + N' | 错误信息: ' + ERROR_MESSAGE();
    END CATCH

    FETCH NEXT FROM tableCursor INTO @SchemaName, @TableName;
END;

-- 清理资源
CLOSE tableCursor;
DEALLOCATE tableCursor;

PRINT N'操作完成!请检查输出信息确认结果。';

PostgreSQL清空备节点数据脚本:

DO $$
DECLARE
    table_name TEXT;
BEGIN
    -- 获取所有用户表
    FOR table_name IN 
        SELECT tablename 
        FROM pg_tables 
        WHERE schemaname = 'public'
         
    LOOP
        -- 清空表并重置序列
        EXECUTE 'TRUNCATE TABLE ' || quote_ident(table_name) || ' RESTART IDENTITY CASCADE';
        RAISE NOTICE '已清空表: %', table_name;
    END LOOP;
END 
$$;

Sqlserver自动创建主键脚本(遍历某个库所有表,1.如果有主键则跳过。2.如果有自增列却没有主键,则将自增列设置为主键。3.如果没有自增列也没有主键,则自动创建Bigint类型的自增主键):

DECLARE @DatabaseName NVARCHAR(128) = N'AA-1' -- 替换为你的数据库名称

-- 切换到目标数据库
USE [AA-1] -- 这里也需要替换为实际的数据库名称

DECLARE @TableSchema NVARCHAR(128)
DECLARE @TableName NVARCHAR(128)
DECLARE @ColumnName NVARCHAR(128)
DECLARE @Sql NVARCHAR(MAX)
DECLARE @PKName NVARCHAR(128)

-- 创建游标遍历所有用户表
DECLARE table_cursor CURSOR FOR
SELECT 
    TABLE_SCHEMA, 
    TABLE_NAME 
FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_TYPE = 'BASE TABLE'
  AND TABLE_CATALOG = @DatabaseName

OPEN table_cursor
FETCH NEXT FROM table_cursor INTO @TableSchema, @TableName

WHILE @@FETCH_STATUS = 0
BEGIN
    -- 检查表是否有主键
    IF NOT EXISTS (
        SELECT 1 
        FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
        JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu 
            ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME
        WHERE tc.CONSTRAINT_TYPE = 'PRIMARY KEY'
          AND tc.TABLE_SCHEMA = @TableSchema
          AND tc.TABLE_NAME = @TableName
          AND tc.TABLE_CATALOG = @DatabaseName
    )
    BEGIN
        -- 检查表是否有自增列
        IF EXISTS (
            SELECT 1 
            FROM INFORMATION_SCHEMA.COLUMNS 
            WHERE TABLE_SCHEMA = @TableSchema 
              AND TABLE_NAME = @TableName 
              AND TABLE_CATALOG = @DatabaseName
              AND COLUMNPROPERTY(
                  OBJECT_ID(QUOTENAME(@TableSchema) + '.' + QUOTENAME(@TableName)), 
                  COLUMN_NAME, 
                  'IsIdentity'
              ) = 1
        )
        BEGIN
            -- 获取自增列名
            SELECT @ColumnName = COLUMN_NAME
            FROM INFORMATION_SCHEMA.COLUMNS 
            WHERE TABLE_SCHEMA = @TableSchema 
              AND TABLE_NAME = @TableName 
              AND TABLE_CATALOG = @DatabaseName
              AND COLUMNPROPERTY(
                  OBJECT_ID(QUOTENAME(@TableSchema) + '.' + QUOTENAME(@TableName)), 
                  COLUMN_NAME, 
                  'IsIdentity'
              ) = 1
            
            -- 设置自增列为主键
            SET @PKName = 'PK_' + @TableName
            SET @Sql = N'ALTER TABLE ' + QUOTENAME(@TableSchema) + '.' + QUOTENAME(@TableName) + 
                      N' ADD CONSTRAINT ' + QUOTENAME(@PKName) + 
                      N' PRIMARY KEY (' + QUOTENAME(@ColumnName) + N')'
            
            PRINT N'为表 ' + @TableSchema + '.' + @TableName + N' 设置自增列为主键: ' + @Sql
            EXEC sp_executesql @Sql
        END
        ELSE
        BEGIN
            -- 创建PanguId自增主键
            SET @PKName = 'PK_' + @TableName
            SET @Sql = N'
            IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS 
                          WHERE TABLE_SCHEMA = @Schema 
                            AND TABLE_NAME = @Table 
                            AND COLUMN_NAME = ''PanguId'')
            BEGIN
                ALTER TABLE ' + QUOTENAME(@TableSchema) + '.' + QUOTENAME(@TableName) + 
                N' ADD PanguId bigint IDENTITY(1,1) NOT NULL
            END
            
            ALTER TABLE ' + QUOTENAME(@TableSchema) + '.' + QUOTENAME(@TableName) + 
            N' ADD CONSTRAINT ' + QUOTENAME(@PKName) + 
            N' PRIMARY KEY (PanguId)'
            
            PRINT N'为表 ' + @TableSchema + '.' + @TableName + N' 创建PanguId自增主键'
            
            EXEC sp_executesql @Sql, 
                N'@Schema NVARCHAR(128), @Table NVARCHAR(128)', 
                @Schema = @TableSchema, @Table = @TableName
        END
    END
    ELSE
    BEGIN
        PRINT N'表 ' + @TableSchema + '.' + @TableName + N' 已有主键,跳过处理'
    END
    
    FETCH NEXT FROM table_cursor INTO @TableSchema, @TableName
END

CLOSE table_cursor
DEALLOCATE table_cursor
 
  • 邮件提醒

如果需要进行邮件提醒,则需要在【邮件提醒】标签页做相关配置,默认是设置了163的SMTP服务器,也可设置其他邮箱服务器,发件人需要是SMTP服务器所指的邮箱类型,收件人可以是其他邮箱,授权码需要登录163邮箱进行设置,如下图所示

开启pop3/smtp

配置完后,可先点击【邮件测试】,确认邮件发送没问题,然后点击【保存配置】,如下图所示

邮件配置

以下情况会进行邮件提醒:

  • VIP切换时,会发送邮件提醒
  • 在添加对方IP后,主节点会对它们进行监测,对方IP连接异常时会发送邮件提醒(防止主节点宕机没有备节点可以切换)
  • 在添加本机Web服务Url后,备节点如果检测到Web服务异常后,会发送邮件提醒(防止主节点Web服务异常没有可用的备节点)
  • 在添加本机Windows服务后,备节点如果检测到Windows服务异常,会发送邮件提醒(防止主节点Windows服务异常没有可用的备节点)
  • 在开启Mysql健康检测的情况下,备节点断联或同步异常,会发送邮件提醒(防止主节点宕机切换后数据异常)
  • Sqlserver数据同步异常停止任务时会发送邮件

邮件格式如下图所示,

移动端邮件提醒

关于开机自启动

  • 在【IP漂移】点击运行成功后,会保存相关信息,下次打开软件将自动运行
  • 在【执行管理】配置后,下次打开将自动运行
  • 在【文件同步】配置后,下次打开将自动运行
  • 在【mysql主从配置】开启健康检测成功后,会保存mysql设置的相关信息,下次打开软件将自动开启健康检测
  • 在【数据同步】添加任务后,下次打开将自动运行
  • 将软件设置为快捷方式,然后Win+R输入shell:startup,将快捷方式拖入该目录
  • Win+R输入gpedit.msc打开组策略,依次展开计算机配置—>Windows设置—>安全设置—>本地策略—>安全选项—>用户账户控制:以管理员批准模式运行所有管理员,设置为已禁用
  • Win+R输入control userpasswords2,取消【要使用本计算机,用户必须输入用户名和密码】

清除配置

删除Config文件夹即可