This is an automated email from the ASF dual-hosted git repository.
hefengen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git
The following commit(s) were added to refs/heads/master by this push:
new ff289b43eb [type:feat] bootstrap instances status (#5950)
ff289b43eb is described below
commit ff289b43eb0b51edcd58a9dc72ba53ca315c57ca
Author: aias00 <[email protected]>
AuthorDate: Fri Jun 20 09:55:52 2025 +0800
[type:feat] bootstrap instances status (#5950)
* [feat] instance info report
* [feat] instance info report
* [feat] instance info sql
* [feat] instance info
* [feat] instance info
* [feat] instance info
* [feat] instance info
* [feat] instance info
* [feat] instance info, modify SystemInfoUtil
* [feat] remove useless code
* [feat] instance info, client
* [feat] instance info, client
* [feat] instance info, client
* [feat] instance info, client
* [feat] instance info, client
* add instance_state field;add http instance info
* [feat] instance info curd
---------
Co-authored-by: ‘xcsnx’ <‘[email protected]’>
Co-authored-by: zhengpeng <[email protected]>
---
.gitignore | 3 +
db/init/mysql/schema.sql | 32 +-
db/init/ob/schema.sql | 20 +-
db/init/og/create-table.sql | 25 ++
db/init/oracle/schema.sql | 26 ++
db/init/pg/create-table.sql | 25 ++
db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql | 2 +-
db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql | 15 +
db/upgrade/2.7.0-upgrade-2.7.1-ob.sql | 12 +
db/upgrade/2.7.0-upgrade-2.7.1-og.sql | 25 ++
db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql | 26 ++
db/upgrade/2.7.0-upgrade-2.7.1-pg.sql | 25 ++
.../admin/controller/InstanceController.java | 96 +++++
.../subscriber/URIRegisterExecutorSubscriber.java | 2 +-
.../shenyu/admin/mapper/InstanceInfoMapper.java | 106 ++++++
.../shenyu/admin/model/dto/InstanceInfoDTO.java | 217 +++++++++++
.../shenyu/admin/model/entity/InstanceInfoDO.java | 409 +++++++++++++++++++++
.../shenyu/admin/model/query/InstanceQuery.java | 202 ++++++++++
.../admin/model/query/InstanceQueryCondition.java | 101 +++++
.../shenyu/admin/model/vo/InstanceInfoVO.java | 215 +++++++++++
.../shenyu/admin/service/InstanceInfoService.java | 50 +++
.../service/impl/InstanceInfoServiceImpl.java | 111 ++++++
.../src/main/resources/application-mysql.yml | 2 +-
shenyu-admin/src/main/resources/application.yml | 2 +-
.../resources/mappers/instance-info-sqlmap.xml | 154 ++++++++
.../main/resources/mappers/meta-data-sqlmap.xml | 1 -
.../src/main/resources/sql-script/h2/schema.sql | 28 ++
.../ShenyuClientURIExecutorSubscriber.java | 8 +-
shenyu-common/pom.xml | 7 +
.../common/constant/InstanceTypeConstants.java | 32 +-
.../shenyu/common/utils/SystemInfoUtils.java | 68 ++++
.../shenyu/register/common/type/DataType.java | 5 +
32 files changed, 2019 insertions(+), 33 deletions(-)
diff --git a/.gitignore b/.gitignore
index 648f8ec059..ed771e556c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -47,3 +47,6 @@ Thumbs.db
*.lock
.factorypath
+
+# Private individual user cursor rules
+.cursor/rules/_*.mdc
diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql
index f88987dc86..d46058a5e2 100644
--- a/db/init/mysql/schema.sql
+++ b/db/init/mysql/schema.sql
@@ -2543,6 +2543,21 @@ INSERT INTO `permission` (`id`, `object_id`,
`resource_id`, `date_created`, `dat
INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1792779493541343266', '1346358560427216896',
'1792749362445840485', '2024-06-25 20:00:00.000', '2024-06-25 20:00:00.000');
INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1792779493541343267', '1346358560427216896',
'1792749362445840486', '2024-06-25 20:00:00.000', '2024-06-25 20:00:00.000');
+
+INSERT INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483300','1357956838021890048','SHENYU.MENU.SYSTEM.MANAGMENT.INSTANCE','instance','/config/instance','instance','1','6','ordered-list','0','0','','1');
+INSERT INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483301','1346778036402483300','SHENYU.BUTTON.SYSTEM.LIST','','','','2','0','','1','0','system:instance:list','1');
+INSERT INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483302','1346778036402483300','SHENYU.BUTTON.SYSTEM.DELETE','','','','2','1','','1','0','system:instance:delete','1');
+INSERT INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483303','1346778036402483300','SHENYU.BUTTON.SYSTEM.ADD','','','','2','2','','1','0','system:instance:add','1');
+INSERT INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483304','1346778036402483300','SHENYU.BUTTON.SYSTEM.ENABLE','','','','2','3','','1','0','system:instance:disable','1');
+INSERT INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483305','1346778036402483300','SHENYU.BUTTON.SYSTEM.EDIT','','','','2','4','','1','0','system:instance:edit','1');
+
+INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1697141926281382720', '1346358560427216896',
'1346778036402483300', '2023-08-31 06:59:01', '2023-08-31 06:59:01');
+INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1697141926281382721', '1346358560427216896',
'1346778036402483301', '2023-08-31 07:22:07', '2023-08-31 07:22:07');
+INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1697141926281382722', '1346358560427216896',
'1346778036402483302', '2023-08-31 07:14:26', '2023-08-31 07:14:26');
+INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1697141926281382723', '1346358560427216896',
'1346778036402483303', '2023-08-31 07:22:07', '2023-08-31 07:22:07');
+INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1697141926281382724', '1346358560427216896',
'1346778036402483304', '2023-08-31 07:18:37', '2023-08-31 07:18:37');
+INSERT INTO `permission` (`id`, `object_id`, `resource_id`, `date_created`,
`date_updated`) VALUES ('1697141926281382725', '1346358560427216896',
'1346778036402483305', '2023-08-31 07:18:37', '2023-08-31 07:18:37');
+
-- ----------------------------
-- Table structure for scale
-- ----------------------------
@@ -2592,10 +2607,25 @@ CREATE TABLE IF NOT EXISTS `scale_history`
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci
ROW_FORMAT = Dynamic;
-CREATE TABLE `namespace_user_rel` (
+DROP TABLE IF EXISTS `namespace_user_rel`;
+CREATE TABLE IF NOT EXISTS `namespace_user_rel` (
`id` varchar(128) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'primary key',
`namespace_id` varchar(50) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'namespace_id',
`user_id` varchar(128) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'user_id',
`date_created` timestamp NOT NULL
DEFAULT CURRENT_TIMESTAMP COMMENT 'date_created',
`date_updated` timestamp NOT NULL
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'date_updated'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='namespace user relation ';
+
+DROP TABLE IF EXISTS `instance_info`;
+CREATE TABLE IF NOT EXISTS `instance_info` (
+ `id` varchar(128) NOT
NULL COMMENT 'primary key',
+ `namespace_id` varchar(50) NOT NULL COMMENT 'namespace_id',
+ `instance_ip` varchar(128) NOT NULL COMMENT 'instance_ip',
+ `instance_port` varchar(128) NOT NULL COMMENT 'instance_port',
+ `instance_type` varchar(128) NOT NULL COMMENT 'instance_type',
+ `instance_info` text NOT NULL COMMENT 'instance_info',
+ `instance_state` tinyint(4) NOT NULL COMMENT '0-unknown 1-online
2-offline',
+ `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT
'date_created',
+ `date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP COMMENT 'date_updated',
+ PRIMARY KEY (`id`)
+);
\ No newline at end of file
diff --git a/db/init/ob/schema.sql b/db/init/ob/schema.sql
index aae8b89047..3878810db5 100644
--- a/db/init/ob/schema.sql
+++ b/db/init/ob/schema.sql
@@ -2485,7 +2485,7 @@ INSERT INTO `permission` (`id`, `object_id`,
`resource_id`, `date_created`, `dat
-CREATE TABLE `namespace_user_rel` (
+CREATE TABLE IF NOT EXISTS `namespace_user_rel` (
`id` varchar(128) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'primary key',
`namespace_id` varchar(50) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'namespace_id',
`user_id` varchar(128) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'user_id',
@@ -2493,6 +2493,20 @@ CREATE TABLE `namespace_user_rel` (
`date_updated` timestamp NOT NULL
DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'date_updated'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='namespace user relation ';
+
+CREATE TABLE IF NOT EXISTS instance_info (
+ `id` varchar(128) NOT NULL COMMENT 'primary key',
+ `namespace_id` varchar(50) NOT NULL COMMENT 'namespace_id',
+ `instance_port` varchar(128) NOT NULL COMMENT 'instance_port',
+ `instance_ip` varchar(128) NOT NULL COMMENT 'instance_ip',
+ `instance_type` varchar(128) NOT NULL COMMENT 'instance_type',
+ `instance_info` text NOT NULL COMMENT 'instance_info',
+ `instance_state` tiny(4) NOT NULL COMMENT 'instance_state',
+ `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT
'date_created',
+ `date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP COMMENT 'date_updated',
+ PRIMARY KEY (`id`)
+);
+
INSERT INTO `permission` VALUES ('1697146860569642741', '1346358560427216896',
'1844026099075554850', '2023-08-31 06:59:01', '2023-08-31 06:59:01');
INSERT INTO `permission` VALUES ('1697146860569642742', '1346358560427216896',
'1844026099075554851', '2023-08-31 07:22:07', '2023-08-31 07:22:07');
INSERT INTO `permission` VALUES ('1697146860569642743', '1346358560427216896',
'1844026099075554852', '2023-08-31 07:14:26', '2023-08-31 07:14:26');
@@ -2533,7 +2547,9 @@ INSERT INTO `shenyu_dict` VALUES ('1679002911061737583',
'postRole', 'ROLE_TYPE_
INSERT INTO `namespace_plugin_rel` (`id`,`namespace_id`,`plugin_id`, `config`,
`sort`, `enabled`, `date_created`, `date_updated`) VALUES
('1801816010882822189','649330b6-c2d7-4edc-be8e-8a54df9eb385','52', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
INSERT INTO `namespace_plugin_rel` (`id`,`namespace_id`,`plugin_id`, `config`,
`sort`, `enabled`, `date_created`, `date_updated`) VALUES
('1801816010882822190','649330b6-c2d7-4edc-be8e-8a54df9eb385','53', NULL, 65,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
-INSERT INTO `shenyu_dict` VALUES ('1679002911061737490', 'aiTokenLimitType',
'CONTEXT_PATH_KEY_RESOLVER', 'contextPath', 'contextPath', 'Rate limit by
contextPath', 0, 1, '2024-02-07 14:31:49', '2024-02-07 14:31:49');
+
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737490', 'aiTokenLimitType',
'DEFAULT_KEY_RESOLVER', 'default', 'default', 'Rate limit by default', 0, 1,
'2024-02-07 14:31:49', '2024-02-07 14:31:49');
+INSERT INTO `shenyu_dict` VALUES ('1679002911061737496', 'aiTokenLimitType',
'CONTEXT_PATH_KEY_RESOLVER', 'contextPath', 'contextPath', 'Rate limit by
contextPath', 0, 1, '2024-02-07 14:31:49', '2024-02-07 14:31:49');
INSERT INTO `shenyu_dict` VALUES ('1679002911061737491', 'aiTokenLimitType',
'IP_KEY_RESOLVER', 'ip', 'ip', 'Rate limit by request ip', 1, 1, '2024-02-07
14:31:49', '2024-02-07 14:31:49');
INSERT INTO `shenyu_dict` VALUES ('1679002911061737492', 'aiTokenLimitType',
'URI_KEY_RESOLVER', 'uri', 'uri', 'Rate limit by request uri', 2, 1,
'2024-02-07 14:31:49', '2024-02-07 14:31:49');
INSERT INTO `shenyu_dict` VALUES ('1679002911061737493', 'aiTokenLimitType',
'HEADER_KEY_RESOLVER', 'header', 'header', 'Rate limit by request header', 3,
1, '2024-02-07 14:31:49', '2024-02-07 14:31:49');
diff --git a/db/init/og/create-table.sql b/db/init/og/create-table.sql
index 61a5e23469..fffe27c5f1 100644
--- a/db/init/og/create-table.sql
+++ b/db/init/og/create-table.sql
@@ -2848,6 +2848,30 @@ INSERT INTO "public"."plugin_handle" VALUES
('1722804548510507046', '50', 'maxTo
INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507047', '50',
'stream', 'stream', 3, 1, 6, '{"defaultValue":"false","rule":""}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507048', '50',
'prompt', 'prompt', 2, 1, 7, '{"required":"0","rule":""}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
+
+DROP TABLE IF EXISTS "public"."instance_info";
+CREATE TABLE "public"."instance_info" (
+ "id" varchar(128) NOT NULL,
+ "namespace_id" varchar(50) NOT NULL,
+ "instance_ip" varchar(128) NOT NULL,
+ "instance_port" varchar(128) NOT NULL,
+ "instance_type" varchar(128) NOT NULL,
+ "instance_info" text NOT NULL,
+ "instance_state" int2 NOT NULL,
+ "date_created" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ "date_updated" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ PRIMARY KEY ("id")
+);
+COMMENT ON COLUMN "public"."instance_info"."id" IS 'primary key';
+COMMENT ON COLUMN "public"."instance_info"."namespace_id" IS 'namespace_id';
+COMMENT ON COLUMN "public"."instance_info"."instance_ip" IS 'instance_ip';
+COMMENT ON COLUMN "public"."instance_info"."instance_port" IS 'instance_port';
+COMMENT ON COLUMN "public"."instance_info"."instance_type" IS 'instance_type';
+COMMENT ON COLUMN "public"."instance_info"."instance_info" IS 'instance_info';
+COMMENT ON COLUMN "public"."instance_info"."instance_state" IS
'instance_state';
+COMMENT ON COLUMN "public"."instance_info"."date_created" IS 'create time';
+COMMENT ON COLUMN "public"."instance_info"."date_updated" IS 'update time';
+
INSERT INTO "public"."plugin" VALUES ('52', 'aiPrompt', null, 'Ai', 170, 0,
'2023-12-20 18:02:53', '2023-12-20 18:02:53', null);
INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507140', '52',
'prepend', 'prepend', 2, 3, 1, '{"required":"0","rule":""}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
@@ -2873,6 +2897,7 @@ INSERT INTO "public"."shenyu_dict" VALUES
('1679002911061737583', 'postRole', 'R
INSERT INTO "public"."namespace_plugin_rel" ("id","namespace_id","plugin_id",
"config", "sort", "enabled", "date_created", "date_updated") VALUES
('1801816010882822189','649330b6-c2d7-4edc-be8e-8a54df9eb385','52', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
+
INSERT INTO "public"."resource" VALUES ('1844026099075534859',
'1346775491550474240', 'aiTokenLimiter', 'aiTokenLimiter',
'/plug/aiTokenLimiter', 'aiTokenLimiter', 1, 0, 'pic-center', 0, 0, '', 1,
'2022-05-25 18:02:58', '2022-05-25 18:02:58');
INSERT INTO "public"."resource" VALUES ('1844026099075534860',
'1844026099075534859', 'SHENYU.BUTTON.PLUGIN.SELECTOR.ADD', '', '', '', 2, 0,
'', 1, 0, 'plugin:aiTokenLimiterSelector:add', 1, '2022-05-25 18:02:58',
'2022-05-25 18:02:58');
INSERT INTO "public"."resource" VALUES ('1844026099075534861',
'1844026099075534859', 'SHENYU.BUTTON.PLUGIN.SELECTOR.QUERY', '', '', '', 2, 0,
'', 1, 0, 'plugin:aiTokenLimiterSelector:query', 1, '2022-05-25 18:02:58',
'2022-05-25 18:02:58');
diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql
index 74f03f5b54..5b32ffc1e9 100644
--- a/db/init/oracle/schema.sql
+++ b/db/init/oracle/schema.sql
@@ -3147,6 +3147,31 @@ VALUES ('1722804548510507047', '50', 'stream', 'stream',
3, 1, 6, '{"defaultValu
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(id)) */ INTO plugin_handle
(id, plugin_id, field, label, data_type, type, sort, ext_obj, date_created,
date_updated)
VALUES ('1722804548510507048', '50', 'prompt', 'prompt', 2, 1, 7,
'{"required":"0","rule":""}', to_timestamp('2024-01-02 17:20:50.233',
'YYYY-MM-DD HH24:MI:SS.FF3'), to_timestamp('2024-01-02 17:20:50.233',
'YYYY-MM-DD HH24:MI:SS.FF3'));
+
+CREATE TABLE instance_info (
+ id varchar2(128) NOT NULL,
+ namespace_id varchar2(50) NOT NULL,
+ instance_ip varchar2(128) NOT NULL,
+ instance_port varchar2(128) NOT NULL,
+ instance_type varchar2(128) NOT NULL,
+ instance_info clob NOT NULL,
+ instance_state number NOT NULL,
+ date_created timestamp(3) DEFAULT SYSTIMESTAMP NOT NULL,
+ date_updated timestamp(3) DEFAULT SYSTIMESTAMP NOT NULL,
+ CONSTRAINT instance_info_pk PRIMARY KEY (id)
+);
+
+COMMENT ON TABLE instance_info IS 'Instance information table';
+COMMENT ON COLUMN instance_info.id IS 'primary key';
+COMMENT ON COLUMN instance_info.namespace_id IS 'namespace_id';
+COMMENT ON COLUMN instance_info.instance_ip IS 'instance_ip';
+COMMENT ON COLUMN instance_info.instance_port IS 'instance_port';
+COMMENT ON COLUMN instance_info.instance_type IS 'instance_type';
+COMMENT ON COLUMN instance_info.instance_info IS 'instance_info';
+COMMENT ON COLUMN instance_info.instance_state IS 'instance_state';
+COMMENT ON COLUMN instance_info.date_created IS 'create time';
+COMMENT ON COLUMN instance_info.date_updated IS 'update time';
+
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(permission(id)) */ INTO permission (id,
object_id, resource_id, date_created, date_updated)
VALUES ('1697146860569642741', '1346358560427216896', '1844026099075554850',
to_timestamp('2023-08-31 06:59:01', 'YYYY-MM-DD HH24:MI:SS'),
to_timestamp('2023-08-31 06:59:01', 'YYYY-MM-DD HH24:MI:SS'));
@@ -3237,6 +3262,7 @@ VALUES ('1679002911061737583', 'postRole',
'ROLE_TYPE_USER', 'USER', 'user', 'us
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(namespace_plugin_rel(id)) */ INTO
namespace_plugin_rel (id, namespace_id, plugin_id, config, sort, enabled,
date_created, date_updated)
VALUES ('1801816010882822189', '649330b6-c2d7-4edc-be8e-8a54df9eb385', '52',
NULL, 171, 0, to_timestamp('2022-05-25 18:02:53', 'YYYY-MM-DD HH24:MI:SS'),
to_timestamp('2022-05-25 18:02:53', 'YYYY-MM-DD HH24:MI:SS'));
+
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(resource(id)) */ INTO resource (id,
parent_id, title, name, url, component, resource_type, sort, icon, is_leaf,
is_route, perms, status)
VALUES ('1844026099075534859', '1346775491550474240', 'aiTokenLimiter',
'aiTokenLimiter', '/plug/aiTokenLimiter', 'aiTokenLimiter', 1, 0, 'pic-center',
0, 0, '', 1);
diff --git a/db/init/pg/create-table.sql b/db/init/pg/create-table.sql
index df6cc0297a..0e171d5020 100644
--- a/db/init/pg/create-table.sql
+++ b/db/init/pg/create-table.sql
@@ -2969,6 +2969,30 @@ INSERT INTO "public"."plugin_handle" VALUES
('1722804548510507046', '50', 'maxTo
INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507047', '50',
'stream', 'stream', 3, 1, 6, '{"defaultValue":"false","rule":""}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507048', '50',
'prompt', 'prompt', 2, 1, 7, '{"required":"0","rule":""}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
+
+DROP TABLE IF EXISTS "public"."instance_info";
+CREATE TABLE "public"."instance_info" (
+ "id" varchar(128) NOT NULL,
+ "namespace_id" varchar(50) NOT NULL,
+ "instance_ip" varchar(128) NOT NULL,
+ "instance_port" varchar(128) NOT NULL,
+ "instance_type" varchar(128) NOT NULL,
+ "instance_info" text NOT NULL,
+ "instance_state" int2 NOT NULL,
+ "date_created" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ "date_updated" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ PRIMARY KEY ("id")
+);
+COMMENT ON COLUMN "public"."instance_info"."id" IS 'primary key';
+COMMENT ON COLUMN "public"."instance_info"."namespace_id" IS 'namespace_id';
+COMMENT ON COLUMN "public"."instance_info"."instance_ip" IS 'instance_ip';
+COMMENT ON COLUMN "public"."instance_info"."instance_port" IS 'instance_port';
+COMMENT ON COLUMN "public"."instance_info"."instance_type" IS 'instance_type';
+COMMENT ON COLUMN "public"."instance_info"."instance_info" IS 'instance_info';
+COMMENT ON COLUMN "public"."instance_info"."instance_state" IS
'instance_state';
+COMMENT ON COLUMN "public"."instance_info"."date_created" IS 'create time';
+COMMENT ON COLUMN "public"."instance_info"."date_updated" IS 'update time';
+
INSERT INTO "public"."permission" VALUES ('1697146860569642741',
'1346358560427216896', '1844026099075554850', '2023-08-31 06:59:01',
'2023-08-31 06:59:01');
INSERT INTO "public"."permission" VALUES ('1697146860569642742',
'1346358560427216896', '1844026099075554851', '2023-08-31 07:22:07',
'2023-08-31 07:22:07');
INSERT INTO "public"."permission" VALUES ('1697146860569642743',
'1346358560427216896', '1844026099075554852', '2023-08-31 07:14:26',
'2023-08-31 07:14:26');
@@ -3005,6 +3029,7 @@ INSERT INTO "public"."shenyu_dict" VALUES
('1679002911061737583', 'postRole', 'R
INSERT INTO "public"."namespace_plugin_rel" ("id","namespace_id","plugin_id",
"config", "sort", "enabled", "date_created", "date_updated") VALUES
('1801816010882822189','649330b6-c2d7-4edc-be8e-8a54df9eb385','52', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
+
INSERT INTO "public"."resource" VALUES ('1844026099075534859',
'1346775491550474240', 'aiTokenLimiter', 'aiTokenLimiter',
'/plug/aiTokenLimiter', 'aiTokenLimiter', 1, 0, 'pic-center', 0, 0, '', 1,
'2022-05-25 18:02:58', '2022-05-25 18:02:58');
INSERT INTO "public"."resource" VALUES ('1844026099075534860',
'1844026099075534859', 'SHENYU.BUTTON.PLUGIN.SELECTOR.ADD', '', '', '', 2, 0,
'', 1, 0, 'plugin:aiTokenLimiterSelector:add', 1, '2022-05-25 18:02:58',
'2022-05-25 18:02:58');
INSERT INTO "public"."resource" VALUES ('1844026099075534861',
'1844026099075534859', 'SHENYU.BUTTON.PLUGIN.SELECTOR.QUERY', '', '', '', 2, 0,
'', 1, 0, 'plugin:aiTokenLimiterSelector:query', 1, '2022-05-25 18:02:58',
'2022-05-25 18:02:58');
diff --git a/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql
b/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql
index 2d89c19ac3..1f1203ee95 100755
--- a/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql
+++ b/db/upgrade/2.6.1-upgrade-2.7.0-mysql.sql
@@ -239,7 +239,7 @@ CREATE TABLE IF NOT EXISTS `scale_history`
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci
ROW_FORMAT = Dynamic;
-CREATE TABLE `namespace_user_rel` (
+CREATE TABLE IF NOT EXISTS `namespace_user_rel` (
`id` varchar(128) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'primary key',
`namespace_id` varchar(50) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'namespace_id',
`user_id` varchar(128) COLLATE
utf8mb4_unicode_ci NOT NULL COMMENT 'user_id',
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
index edb4801dcb..8147c4d10a 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql
@@ -67,6 +67,20 @@ INSERT INTO `plugin_handle` VALUES ('1722804548510507046',
'50', 'maxTokens', 'm
INSERT INTO `plugin_handle` VALUES ('1722804548510507047', '50', 'stream',
'stream', 3, 1, 6, '{\"defaultValue\":\"false\",\"rule\":\"\"}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
INSERT INTO `plugin_handle` VALUES ('1722804548510507048', '50', 'prompt',
'prompt', 2, 1, 7, '{\"required\":\"0\",\"rule\":\"\"}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
+
+CREATE TABLE IF NOT EXISTS instance_info (
+ `id` varchar(128) NOT
NULL COMMENT 'primary key',
+ `namespace_id` varchar(50) NOT NULL COMMENT 'namespace_id',
+ `instance_ip` varchar(128) NOT NULL COMMENT 'instance_ip',
+ `instance_port` varchar(128) NOT NULL COMMENT 'instance_port',
+ `instance_type` varchar(128) NOT NULL COMMENT 'instance_type',
+ `instance_info` text NOT NULL COMMENT 'instance_info',
+ `instance_state` tinyint(4) NOT NULL COMMENT '0-unknown 1-online
2offline',
+ `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT
'date_created',
+ `date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP COMMENT 'date_updated',
+ PRIMARY KEY (`id`)
+);
+
INSERT INTO `permission` VALUES ('1697146860569642741', '1346358560427216896',
'1844026099075554850', '2023-08-31 06:59:01', '2023-08-31 06:59:01');
INSERT INTO `permission` VALUES ('1697146860569642742', '1346358560427216896',
'1844026099075554851', '2023-08-31 07:22:07', '2023-08-31 07:22:07');
INSERT INTO `permission` VALUES ('1697146860569642743', '1346358560427216896',
'1844026099075554852', '2023-08-31 07:14:26', '2023-08-31 07:14:26');
@@ -107,6 +121,7 @@ INSERT INTO `shenyu_dict` VALUES ('1679002911061737583',
'postRole', 'ROLE_TYPE_
INSERT INTO `namespace_plugin_rel` (`id`,`namespace_id`,`plugin_id`, `config`,
`sort`, `enabled`, `date_created`, `date_updated`) VALUES
('1801816010882822189','649330b6-c2d7-4edc-be8e-8a54df9eb385','52', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
+
INSERT INTO `plugin` VALUES ('51', 'aiTokenLimiter', NULL, 'Ai', 171, 0,
'2023-12-20 18:02:53', '2023-12-20 18:02:53', null);
INSERT INTO `namespace_plugin_rel` (`id`,`namespace_id`,`plugin_id`, `config`,
`sort`, `enabled`, `date_created`, `date_updated`) VALUES
('1801816010882822188','649330b6-c2d7-4edc-be8e-8a54df9eb385','51', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
index 58bd209e9e..8b89f06470 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-ob.sql
@@ -105,6 +105,18 @@ INSERT INTO `shenyu_dict` VALUES ('1679002911061737583',
'postRole', 'ROLE_TYPE_
INSERT INTO `namespace_plugin_rel` (`id`,`namespace_id`,`plugin_id`, `config`,
`sort`, `enabled`, `date_created`, `date_updated`) VALUES
('1801816010882822189','649330b6-c2d7-4edc-be8e-8a54df9eb385','52', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
+CREATE TABLE IF NOT EXISTS instance_info (
+ `id` varchar(128) NOT
NULL COMMENT 'primary key',
+ `namespace_id` varchar(50) NOT NULL COMMENT 'namespace_id',
+ `instance_ip` varchar(128) NOT NULL COMMENT 'instance_ip',
+ `instance_port` varchar(128) NOT NULL COMMENT 'instance_port',
+ `instance_type` varchar(128) NOT NULL COMMENT 'instance_type',
+ `instance_info` text NOT NULL COMMENT 'instance_info',
+ `instance_state` tiny(4) NOT NULL COMMENT 'instance_state',
+ `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT
'date_created',
+ `date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP COMMENT 'date_updated',
+ PRIMARY KEY (`id`)
+);
INSERT INTO `plugin` VALUES ('51', 'aiTokenLimiter', NULL, 'Ai', 171, 0,
'2023-12-20 18:02:53', '2023-12-20 18:02:53', null);
INSERT INTO `namespace_plugin_rel` (`id`,`namespace_id`,`plugin_id`, `config`,
`sort`, `enabled`, `date_created`, `date_updated`) VALUES
('1801816010882822188','649330b6-c2d7-4edc-be8e-8a54df9eb385','51', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
index e2bef06ac0..67ef81f716 100644
--- a/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-og.sql
@@ -69,6 +69,30 @@ INSERT INTO "public"."plugin_handle" VALUES
('1722804548510507047', '50', 'strea
INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507048', '50',
'prompt', 'prompt', 2, 1, 7, '{"required":"0","rule":""}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
+DROP TABLE IF EXISTS "public"."instance_info";
+CREATE TABLE "public"."instance_info" (
+ "id" varchar(128) NOT NULL,
+ "namespace_id" varchar(50) NOT NULL,
+ "instance_ip" varchar(128) NOT NULL,
+ "instance_port" varchar(128) NOT NULL,
+ "instance_type" varchar(128) NOT NULL,
+ "instance_info" text NOT NULL,
+ "instance_state" int2 NOT NULL,
+ "date_created" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ "date_updated" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ PRIMARY KEY ("id")
+);
+COMMENT ON COLUMN "public"."instance_info"."id" IS 'primary key';
+COMMENT ON COLUMN "public"."instance_info"."namespace_id" IS 'namespace_id';
+COMMENT ON COLUMN "public"."instance_info"."instance_ip" IS 'instance_ip';
+COMMENT ON COLUMN "public"."instance_info"."instance_port" IS 'instance_port';
+COMMENT ON COLUMN "public"."instance_info"."instance_type" IS 'instance_type';
+COMMENT ON COLUMN "public"."instance_info"."instance_info" IS 'instance_info';
+COMMENT ON COLUMN "public"."instance_info"."instance_state" IS
'instance_state';
+COMMENT ON COLUMN "public"."instance_info"."date_created" IS 'create time';
+COMMENT ON COLUMN "public"."instance_info"."date_updated" IS 'update time';
+
+
INSERT INTO "public"."permission" VALUES ('1697146860569642741',
'1346358560427216896', '1844026099075554850', '2023-08-31 06:59:01',
'2023-08-31 06:59:01');
INSERT INTO "public"."permission" VALUES ('1697146860569642742',
'1346358560427216896', '1844026099075554851', '2023-08-31 07:22:07',
'2023-08-31 07:22:07');
INSERT INTO "public"."permission" VALUES ('1697146860569642743',
'1346358560427216896', '1844026099075554852', '2023-08-31 07:14:26',
'2023-08-31 07:14:26');
@@ -105,6 +129,7 @@ INSERT INTO "public"."shenyu_dict" VALUES
('1679002911061737583', 'postRole', 'R
INSERT INTO "public"."namespace_plugin_rel" ("id","namespace_id","plugin_id",
"config", "sort", "enabled", "date_created", "date_updated") VALUES
('1801816010882822189','649330b6-c2d7-4edc-be8e-8a54df9eb385','52', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
+
INSERT INTO "public"."plugin" VALUES ('51', 'aiTokenLimiter', NULL, 'Ai', 171,
0, '2023-12-20 18:02:53', '2023-12-20 18:02:53', null);
INSERT INTO "public"."namespace_plugin_rel" VALUES
('1801816010882822188','649330b6-c2d7-4edc-be8e-8a54df9eb385','51', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
index 3b95582edf..f8328f5d9d 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql
@@ -146,6 +146,31 @@ INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(id))
*/ INTO plugin_handle (
VALUES ('1722804548510507048', '50', 'prompt', 'prompt', 2, 1, 7,
'{"required":"0","rule":""}', to_timestamp('2024-01-02 17:20:50.233',
'YYYY-MM-DD HH24:MI:SS.FF3'), to_timestamp('2024-01-02 17:20:50.233',
'YYYY-MM-DD HH24:MI:SS.FF3'));
+CREATE TABLE instance_info (
+ id varchar2(128) NOT NULL,
+ namespace_id varchar2(50) NOT NULL,
+ instance_ip varchar2(128) NOT NULL,
+ instance_port varchar2(128) NOT NULL,
+ instance_type varchar2(128) NOT NULL,
+ instance_info clob NOT NULL,
+ instance_state number NOT NULL,
+ date_created timestamp(3) DEFAULT SYSTIMESTAMP NOT NULL,
+ date_updated timestamp(3) DEFAULT SYSTIMESTAMP NOT NULL,
+ CONSTRAINT instance_info_pk PRIMARY KEY (id)
+);
+
+COMMENT ON TABLE instance_info IS 'Instance information table';
+COMMENT ON COLUMN instance_info.id IS 'primary key';
+COMMENT ON COLUMN instance_info.namespace_id IS 'namespace_id';
+COMMENT ON COLUMN instance_info.instance_ip IS 'instance_ip';
+COMMENT ON COLUMN instance_info.instance_port IS 'instance_port';
+COMMENT ON COLUMN instance_info.instance_type IS 'instance_type';
+COMMENT ON COLUMN instance_info.instance_info IS 'instance_info';
+COMMENT ON COLUMN instance_info.instance_state IS 'instance_state';
+COMMENT ON COLUMN instance_info.date_created IS 'create time';
+COMMENT ON COLUMN instance_info.date_updated IS 'update time';
+
+
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(permission(id)) */ INTO permission (id,
object_id, resource_id, date_created, date_updated)
VALUES ('1697146860569642741', '1346358560427216896', '1844026099075554850',
to_timestamp('2023-08-31 06:59:01', 'YYYY-MM-DD HH24:MI:SS'),
to_timestamp('2023-08-31 06:59:01', 'YYYY-MM-DD HH24:MI:SS'));
@@ -236,6 +261,7 @@ VALUES ('1679002911061737583', 'postRole',
'ROLE_TYPE_USER', 'USER', 'user', 'us
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(namespace_plugin_rel(id)) */ INTO
namespace_plugin_rel (id, namespace_id, plugin_id, config, sort, enabled,
date_created, date_updated)
VALUES ('1801816010882822189', '649330b6-c2d7-4edc-be8e-8a54df9eb385', '52',
NULL, 171, 0, to_timestamp('2022-05-25 18:02:53', 'YYYY-MM-DD HH24:MI:SS'),
to_timestamp('2022-05-25 18:02:53', 'YYYY-MM-DD HH24:MI:SS'));
+
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin(id)) */ INTO plugin (id, name,
config, role, sort, enabled, date_created, date_updated, plugin_jar) VALUES
('51', 'aiTokenLimiter', NULL, 'Ai', 171, 0, to_timestamp('2023-12-20
18:02:53', 'YYYY-MM-DD HH24:MI:SS'), to_timestamp('2023-12-20 18:02:53',
'YYYY-MM-DD HH24:MI:SS'), null);
INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX (namespace_plugin_rel(id)) */ INTO
namespace_plugin_rel (id,namespace_id,plugin_id, config, sort, enabled) VALUES
('1801816010882822188','649330b6-c2d7-4edc-be8e-8a54df9eb385','51', NULL, 171,
0);
diff --git a/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
b/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
index 27e66cd524..a73fd053d0 100755
--- a/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
+++ b/db/upgrade/2.7.0-upgrade-2.7.1-pg.sql
@@ -68,6 +68,30 @@ INSERT INTO "public"."plugin_handle" VALUES
('1722804548510507047', '50', 'strea
INSERT INTO "public"."plugin_handle" VALUES ('1722804548510507048', '50',
'prompt', 'prompt', 2, 1, 7, '{"required":"0","rule":""}', '2024-01-02
17:20:50.233', '2024-01-02 17:20:50.233');
+DROP TABLE IF EXISTS "public"."instance_info";
+CREATE TABLE "public"."instance_info" (
+ "id" varchar(128) NOT NULL,
+ "namespace_id" varchar(50) NOT NULL,
+ "instance_ip" varchar(128) NOT NULL,
+ "instance_port" varchar(128) NOT NULL,
+ "instance_type" varchar(128) NOT NULL,
+ "instance_info" text NOT NULL,
+ "instance_state" int2 NOT NULL,
+ "date_created" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ "date_updated" timestamp(3) NOT NULL DEFAULT timezone('UTC-8'::text,
(now())::timestamp(0) without time zone),
+ PRIMARY KEY ("id")
+);
+COMMENT ON COLUMN "public"."instance_info"."id" IS 'primary key';
+COMMENT ON COLUMN "public"."instance_info"."namespace_id" IS 'namespace_id';
+COMMENT ON COLUMN "public"."instance_info"."instance_ip" IS 'instance_ip';
+COMMENT ON COLUMN "public"."instance_info"."instance_port" IS 'instance_port';
+COMMENT ON COLUMN "public"."instance_info"."instance_type" IS 'instance_type';
+COMMENT ON COLUMN "public"."instance_info"."instance_info" IS 'instance_info';
+COMMENT ON COLUMN "public"."instance_info"."instance_state" IS
'instance_state';
+COMMENT ON COLUMN "public"."instance_info"."date_created" IS 'create time';
+COMMENT ON COLUMN "public"."instance_info"."date_updated" IS 'update time';
+
+
INSERT INTO "public"."permission" VALUES ('1697146860569642741',
'1346358560427216896', '1844026099075554850', '2023-08-31 06:59:01',
'2023-08-31 06:59:01');
INSERT INTO "public"."permission" VALUES ('1697146860569642742',
'1346358560427216896', '1844026099075554851', '2023-08-31 07:22:07',
'2023-08-31 07:22:07');
INSERT INTO "public"."permission" VALUES ('1697146860569642743',
'1346358560427216896', '1844026099075554852', '2023-08-31 07:14:26',
'2023-08-31 07:14:26');
@@ -104,6 +128,7 @@ INSERT INTO "public"."shenyu_dict" VALUES
('1679002911061737583', 'postRole', 'R
INSERT INTO "public"."namespace_plugin_rel" ("id","namespace_id","plugin_id",
"config", "sort", "enabled", "date_created", "date_updated") VALUES
('1801816010882822189','649330b6-c2d7-4edc-be8e-8a54df9eb385','52', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
+
INSERT INTO "public"."plugin" VALUES ('51', 'aiTokenLimiter', NULL, 'Ai', 171,
0, '2023-12-20 18:02:53', '2023-12-20 18:02:53', null);
INSERT INTO "public"."namespace_plugin_rel" VALUES
('1801816010882822188','649330b6-c2d7-4edc-be8e-8a54df9eb385','51', NULL, 171,
0, '2022-05-25 18:02:53.000', '2022-05-25 18:02:53.000');
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java
new file mode 100644
index 0000000000..a2d5218821
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/controller/InstanceController.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.controller;
+
+import jakarta.validation.constraints.NotNull;
+import org.apache.shenyu.admin.aspect.annotation.RestApi;
+import org.apache.shenyu.admin.model.page.CommonPager;
+import org.apache.shenyu.admin.model.page.PageParameter;
+import org.apache.shenyu.admin.model.query.InstanceQuery;
+import org.apache.shenyu.admin.model.query.InstanceQueryCondition;
+import org.apache.shenyu.admin.model.result.ShenyuAdminResult;
+import org.apache.shenyu.admin.model.vo.InstanceInfoVO;
+import org.apache.shenyu.admin.service.InstanceInfoService;
+import org.apache.shenyu.admin.service.PageService;
+import org.apache.shenyu.admin.utils.ShenyuResultMessage;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * this is instance controller.
+ */
+@RestApi("/instance")
+public class InstanceController implements
PagedController<InstanceQueryCondition, InstanceInfoVO> {
+
+ private final InstanceInfoService instanceInfoService;
+
+ public InstanceController(final InstanceInfoService instanceInfoService) {
+ this.instanceInfoService = instanceInfoService;
+ }
+
+ /**
+ * query instance info.
+ *
+ * @param instanceType instance type.
+ * @param instanceIp instance ip.
+ * @param instancePort instance port.
+ * @param namespaceId namespace id.
+ * @param currentPage current page.
+ * @param pageSize page size.
+ * @return {@linkplain ShenyuAdminResult}
+ */
+ @GetMapping
+ public ShenyuAdminResult queryPlugins(@RequestParam(name = "instanceType",
required = false) final String instanceType,
+ @RequestParam(name = "instanceIp",
required = false) final String instanceIp,
+ @RequestParam(name = "instancePort",
required = false) final String instancePort,
+ @RequestParam(name = "namespaceId")
final String namespaceId,
+ @NotNull @RequestParam(name =
"currentPage") final Integer currentPage,
+ @NotNull @RequestParam(name =
"pageSize") final Integer pageSize) {
+ CommonPager<InstanceInfoVO> commonPager =
instanceInfoService.listByPage(
+ new InstanceQuery(
+ new PageParameter(currentPage, pageSize),
+ instanceType,
+ instanceIp,
+ instancePort,
+ namespaceId
+ )
+ );
+ return ShenyuAdminResult.success(ShenyuResultMessage.QUERY_SUCCESS,
commonPager);
+ }
+
+ /**
+ * detail instance info.
+ *
+ * @param id instance id.
+ * @return {@linkplain ShenyuAdminResult}
+ */
+ @GetMapping("/{id}")
+ @RequiresPermissions("system:instance:edit")
+ public ShenyuAdminResult detailInstanceInfo(@PathVariable("id") final
String id) {
+ InstanceInfoVO instanceInfoVO = instanceInfoService.findById(id);
+ return ShenyuAdminResult.success(ShenyuResultMessage.DETAIL_SUCCESS,
instanceInfoVO);
+ }
+
+
+ @Override
+ public PageService<InstanceQueryCondition, InstanceInfoVO> pageService() {
+ return instanceInfoService;
+ }
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java
index 254e268fa0..5ff30e5ebd 100644
---
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/disruptor/subscriber/URIRegisterExecutorSubscriber.java
@@ -95,7 +95,7 @@ public class URIRegisterExecutorSubscriber implements
ExecutorTypeSubscriber<URI
heartbeat.stream().map(URIRegisterDTO::getNamespaceId)
.filter(StringUtils::isNotBlank)
.findFirst()
- .ifPresent(namespaceId ->
service.heartbeat(selectorName, heartbeat, namespaceId));
+ .ifPresent(namespaceId ->
service.heartbeat(selectorName, register, namespaceId));
}
if (CollectionUtils.isNotEmpty(offline)) {
offline.stream().map(URIRegisterDTO::getNamespaceId)
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/InstanceInfoMapper.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/InstanceInfoMapper.java
new file mode 100644
index 0000000000..f1d857813b
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/InstanceInfoMapper.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.mapper;
+
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.shenyu.admin.model.entity.InstanceInfoDO;
+import org.apache.shenyu.admin.model.query.InstanceQuery;
+import org.apache.shenyu.admin.validation.ExistProvider;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * InstanceInfoMapper.
+ */
+@Mapper
+public interface InstanceInfoMapper extends ExistProvider {
+
+ /**
+ * existed.
+ *
+ * @param id id
+ * @return existed
+ */
+ @Override
+ Boolean existed(@Param("id") Serializable id);
+
+ /**
+ * selectAll.
+ *
+ * @return instanceInfoDOList
+ */
+ List<InstanceInfoDO> selectAll();
+
+ /**
+ * selectAllByNamespaceId.
+ *
+ * @param namespaceId the namespaceId
+ * @return instanceInfoDOList
+ */
+ List<InstanceInfoDO> findAllByNamespaceId(String namespaceId);
+
+ /**
+ * selectById.
+ *
+ * @param id the id
+ * @return instanceInfoDO
+ */
+ InstanceInfoDO selectById(String id);
+
+ /**
+ * selectOneByQuery.
+ *
+ * @param instanceQuery {@linkplain InstanceQuery}
+ * @return instanceInfoDO
+ */
+ InstanceInfoDO selectOneByQuery(InstanceQuery instanceQuery);
+
+ /**
+ * select instance list by query.
+ *
+ * @param instanceQuery {@linkplain InstanceQuery}
+ * @return the instance list
+ */
+ List<InstanceInfoDO> selectByQuery(InstanceQuery instanceQuery);
+
+ /**
+ * insert instanceInfoDO.
+ *
+ * @param instanceInfoDO instanceInfoDO.
+ * @return rows
+ */
+ int insert(InstanceInfoDO instanceInfoDO);
+
+ /**
+ * delete discovery by id.
+ *
+ * @param id primary key.
+ * @return rows.
+ */
+ int delete(String id);
+
+ /**
+ * update instanceInfoDO.
+ *
+ * @param instanceInfoDO instanceInfoDO.
+ * @return rows
+ */
+ int updateById(InstanceInfoDO instanceInfoDO);
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceInfoDTO.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceInfoDTO.java
new file mode 100644
index 0000000000..e3dc98a429
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/dto/InstanceInfoDTO.java
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.model.dto;
+
+import jakarta.validation.constraints.NotBlank;
+import org.apache.shenyu.admin.mapper.NamespaceMapper;
+import org.apache.shenyu.admin.validation.annotation.Existed;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * InstanceInfoDTO.
+ */
+public class InstanceInfoDTO implements Serializable {
+
+ private static final long serialVersionUID = 3644412439977354321L;
+
+ /**
+ * instance id.
+ */
+ private String instanceId;
+
+ /**
+ * instance ip.
+ */
+ private String instanceIp;
+
+ /**
+ * instance port.
+ */
+ private String instancePort;
+
+ /**
+ * instance type.
+ */
+ private String instanceType;
+
+ /**
+ * instance info.
+ */
+ private String instanceInfo;
+
+ /**
+ * instance state.
+ */
+ private Integer instanceState;
+
+ /**
+ * namespaceId.
+ */
+ @NotBlank
+ @Existed(message = "namespaceId is not existed", provider =
NamespaceMapper.class)
+ private String namespaceId;
+
+ /**
+ * get getInstanceId.
+ *
+ * @return InstanceId
+ */
+ public String getInstanceId() {
+ return instanceId;
+ }
+
+ /**
+ * set instanceId.
+ *
+ * @param instanceId instanceId
+ */
+ public void setInstanceId(final String instanceId) {
+ this.instanceId = instanceId;
+ }
+
+ /**
+ * get instanceIp.
+ *
+ * @return instanceIp
+ */
+ public String getInstanceIp() {
+ return instanceIp;
+ }
+
+ /**
+ * set instanceIp.
+ *
+ * @param instanceIp instanceIp
+ */
+ public void setInstanceIp(final String instanceIp) {
+ this.instanceIp = instanceIp;
+ }
+
+ /**
+ * get instancePort.
+ *
+ * @return instancePort
+ */
+ public String getInstancePort() {
+ return instancePort;
+ }
+
+ /**
+ * set instancePort.
+ *
+ * @param instancePort instancePort
+ */
+ public void setInstancePort(final String instancePort) {
+ this.instancePort = instancePort;
+ }
+
+ /**
+ * get instanceType.
+ *
+ * @return instanceType
+ */
+ public String getInstanceType() {
+ return instanceType;
+ }
+
+ /**
+ * set instanceType.
+ *
+ * @param instanceType instanceType
+ */
+ public void setInstanceType(final String instanceType) {
+ this.instanceType = instanceType;
+ }
+
+ /**
+ * get instanceInfo.
+ *
+ * @return instanceInfo
+ */
+ public String getInstanceInfo() {
+ return instanceInfo;
+ }
+
+ /**
+ * set instanceInfo.
+ *
+ * @param instanceInfo instanceInfo
+ */
+ public void setInstanceInfo(final String instanceInfo) {
+ this.instanceInfo = instanceInfo;
+ }
+
+ /**
+ * get instanceState.
+ *
+ * @return instanceState
+ */
+ public Integer getInstanceState() {
+ return instanceState;
+ }
+
+ /**
+ * set instanceState.
+ *
+ * @param instanceState instanceState
+ */
+ public void setInstanceState(final Integer instanceState) {
+ this.instanceState = instanceState;
+ }
+
+ /**
+ * get namespaceId.
+ *
+ * @return namespaceId
+ */
+ public String getNamespaceId() {
+ return namespaceId;
+ }
+
+ /**
+ * set namespaceId.
+ *
+ * @param namespaceId namespaceId
+ */
+ public void setNamespaceId(final String namespaceId) {
+ this.namespaceId = namespaceId;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (Objects.isNull(o) || getClass() != o.getClass()) {
+ return false;
+ }
+
+ InstanceInfoDTO that = (InstanceInfoDTO) o;
+ return Objects.equals(instanceIp, that.instanceIp)
+ && Objects.equals(instanceType, that.instanceType)
+ && Objects.equals(instanceInfo, that.instanceInfo)
+ && Objects.equals(namespaceId, that.namespaceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(instanceIp, instanceType, instanceInfo,
namespaceId);
+ }
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java
new file mode 100644
index 0000000000..30adf5f158
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/InstanceInfoDO.java
@@ -0,0 +1,409 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.model.entity;
+
+import org.apache.shenyu.admin.model.dto.InstanceInfoDTO;
+import org.apache.shenyu.common.utils.UUIDUtils;
+
+import java.sql.Timestamp;
+import java.util.Objects;
+
+/**
+ * InstanceInfoDO.
+ */
+public final class InstanceInfoDO extends BaseDO {
+
+ private String instanceIp;
+
+ private String instancePort;
+
+ private String instanceType;
+
+ private String instanceInfo;
+
+ private Integer instanceState;
+
+ private String namespaceId;
+
+ public InstanceInfoDO() {
+
+ }
+
+ /**
+ * InstanceInfoDO.
+ *
+ * @param instanceIp instanceIp
+ * @param instanceType instanceType
+ * @param instanceInfo instanceInfo
+ */
+ public InstanceInfoDO(final String instanceIp, final String instancePort,
final String instanceType, final String instanceInfo) {
+ this.instanceIp = instanceIp;
+ this.instancePort = instancePort;
+ this.instanceType = instanceType;
+ this.instanceInfo = instanceInfo;
+ }
+
+ /**
+ * InstanceInfoDO.
+ *
+ * @param id id
+ * @param dateCreated dateCreated
+ * @param dateUpdated dateUpdated
+ * @param instanceIp instanceIp
+ * @param instancePort instancePort
+ * @param instanceType instanceType
+ * @param instanceInfo instanceInfo
+ */
+ public InstanceInfoDO(final String id, final Timestamp dateCreated, final
Timestamp dateUpdated,
+ final String instanceIp, final String instancePort,
final String instanceType, final String instanceInfo) {
+ super(id, dateCreated, dateUpdated);
+ this.instanceIp = instanceIp;
+ this.instancePort = instancePort;
+ this.instanceType = instanceType;
+ this.instanceInfo = instanceInfo;
+ }
+
+ /**
+ * InstanceInfoDO.
+ *
+ * @param id id
+ * @param dateCreated dateCreated
+ * @param dateUpdated dateUpdated
+ * @param instanceIp instanceIp
+ * @param instanceType instanceType
+ * @param instanceInfo instanceInfo
+ * @param namespaceId namespaceId
+ */
+ public InstanceInfoDO(final String id, final Timestamp dateCreated, final
Timestamp dateUpdated,
+ final String instanceIp, final String instancePort,
final String instanceType, final String instanceInfo,
+ final String namespaceId) {
+ super(id, dateCreated, dateUpdated);
+ this.instanceIp = instanceIp;
+ this.instancePort = instancePort;
+ this.instanceType = instanceType;
+ this.instanceInfo = instanceInfo;
+ this.namespaceId = namespaceId;
+ }
+
+ /**
+ * build InstanceInfoDO.
+ *
+ * @param instanceInfoDTO instanceInfoDTO
+ * @return InstanceInfoDO
+ */
+ public static InstanceInfoDO buildInstanceInfoDO(final InstanceInfoDTO
instanceInfoDTO) {
+ Timestamp currentTime = new Timestamp(System.currentTimeMillis());
+ return InstanceInfoDO.builder()
+ .id(UUIDUtils.getInstance().generateShortUuid())
+ .instanceIp(instanceInfoDTO.getInstanceIp())
+ .instancePort(instanceInfoDTO.getInstancePort())
+ .instanceType(instanceInfoDTO.getInstanceType())
+ .instanceInfo(instanceInfoDTO.getInstanceInfo())
+ .instanceState(instanceInfoDTO.getInstanceState())
+ .namespaceId(instanceInfoDTO.getNamespaceId())
+ .dateCreated(currentTime)
+ .dateUpdated(currentTime)
+ .build();
+ }
+
+ /**
+ * get instanceIp.
+ *
+ * @return instanceIp
+ */
+ public String getInstanceIp() {
+ return instanceIp;
+ }
+
+ /**
+ * set instanceIp.
+ *
+ * @param instanceIp instanceIp
+ */
+ public void setInstanceIp(final String instanceIp) {
+ this.instanceIp = instanceIp;
+ }
+
+ /**
+ * get instancePort.
+ *
+ * @return instancePort
+ */
+ public String getInstancePort() {
+ return instancePort;
+ }
+
+ /**
+ * set instancePort.
+ *
+ * @param instancePort instancePort
+ */
+ public void setInstancePort(final String instancePort) {
+ this.instancePort = instancePort;
+ }
+
+ /**
+ * get instanceType.
+ *
+ * @return instanceType
+ */
+ public String getInstanceType() {
+ return instanceType;
+ }
+
+ /**
+ * set instanceType.
+ *
+ * @param instanceType instanceType
+ */
+ public void setInstanceType(final String instanceType) {
+ this.instanceType = instanceType;
+ }
+
+ /**
+ * get instanceInfo.
+ *
+ * @return instanceInfo
+ */
+ public String getInstanceInfo() {
+ return instanceInfo;
+ }
+
+ /**
+ * set instanceInfo.
+ *
+ * @param instanceInfo instanceInfo
+ */
+ public void setInstanceInfo(final String instanceInfo) {
+ this.instanceInfo = instanceInfo;
+ }
+
+ /**
+ * get instanceState.
+ *
+ * @return instanceState
+ */
+ public Integer getInstanceState() {
+ return instanceState;
+ }
+
+ /**
+ * set instanceState.
+ *
+ * @param instanceState instanceState
+ */
+ public void setInstanceState(final Integer instanceState) {
+ this.instanceState = instanceState;
+ }
+
+ /**
+ * get namespaceId.
+ *
+ * @return namespaceId
+ */
+ public String getNamespaceId() {
+ return namespaceId;
+ }
+
+ /**
+ * set namespaceId.
+ *
+ * @param namespaceId namespaceId
+ */
+ public void setNamespaceId(final String namespaceId) {
+ this.namespaceId = namespaceId;
+ }
+
+ /**
+ * builder.
+ *
+ * @return InstanceInfoDOBuilder
+ */
+ public static InstanceInfoDOBuilder builder() {
+ return new InstanceInfoDOBuilder();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (Objects.isNull(o) || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ InstanceInfoDO instanceInfoDO = (InstanceInfoDO) o;
+ return Objects.equals(instanceIp, instanceInfoDO.instanceIp)
+ && Objects.equals(instancePort, instanceInfoDO.instancePort)
+ && Objects.equals(instanceType, instanceInfoDO.instanceType)
+ && Objects.equals(instanceInfo, instanceInfoDO.instanceInfo)
+ && Objects.equals(instanceState, instanceInfoDO.instanceState)
+ && Objects.equals(namespaceId, instanceInfoDO.namespaceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), instanceIp, instancePort,
instanceType, instanceInfo, instanceState, namespaceId);
+ }
+
+ public static final class InstanceInfoDOBuilder {
+
+ private String id;
+
+ private Timestamp dateCreated;
+
+ private Timestamp dateUpdated;
+
+ private String instanceIp;
+
+ private String instancePort;
+
+ private String instanceType;
+
+ private String instanceInfo;
+
+ private Integer instanceState;
+
+ private String namespaceId;
+
+ private InstanceInfoDOBuilder() {
+
+ }
+
+ /**
+ * id.
+ *
+ * @param id the id
+ * @return InstanceInfoDOBuilder.
+ */
+ public InstanceInfoDOBuilder id(final String id) {
+ this.id = id;
+ return this;
+ }
+
+ /**
+ * dateCreated.
+ *
+ * @param dateCreated the dateCreated.
+ * @return InstanceInfoDOBuilder.
+ */
+ public InstanceInfoDOBuilder dateCreated(final Timestamp dateCreated) {
+ this.dateCreated = dateCreated;
+ return this;
+ }
+
+ /**
+ * dateUpdated.
+ *
+ * @param dateUpdated the dateUpdated.
+ * @return InstanceInfoDOBuilder.
+ */
+ public InstanceInfoDOBuilder dateUpdated(final Timestamp dateUpdated) {
+ this.dateUpdated = dateUpdated;
+ return this;
+ }
+
+ /**
+ * instanceIp.
+ *
+ * @param instanceIp instanceIp
+ * @return InstanceInfoDOBuilder
+ */
+ public InstanceInfoDOBuilder instanceIp(final String instanceIp) {
+ this.instanceIp = instanceIp;
+ return this;
+ }
+
+ /**
+ * instancePort.
+ *
+ * @param instancePort instancePort
+ * @return InstanceInfoDOBuilder
+ */
+ public InstanceInfoDOBuilder instancePort(final String instancePort) {
+ this.instancePort = instancePort;
+ return this;
+ }
+
+ /**
+ * instanceType.
+ *
+ * @param instanceType instanceType
+ * @return InstanceInfoDOBuilder
+ */
+ public InstanceInfoDOBuilder instanceType(final String instanceType) {
+ this.instanceType = instanceType;
+ return this;
+ }
+
+ /**
+ * instanceInfo.
+ *
+ * @param instanceInfo instanceInfo
+ * @return InstanceInfoDOBuilder
+ */
+ public InstanceInfoDOBuilder instanceInfo(final String instanceInfo) {
+ this.instanceInfo = instanceInfo;
+ return this;
+ }
+
+ /**
+ * instanceState.
+ *
+ * @param instanceState instanceState
+ * @return InstanceInfoDOBuilder
+ */
+ public InstanceInfoDOBuilder instanceState(final Integer
instanceState) {
+ this.instanceState = instanceState;
+ return this;
+ }
+
+ /**
+ * namespaceId.
+ *
+ * @param namespaceId namespaceId
+ * @return InstanceInfoDOBuilder
+ */
+ public InstanceInfoDOBuilder namespaceId(final String namespaceId) {
+ this.namespaceId = namespaceId;
+ return this;
+ }
+
+
+ /**
+ * build InstanceInfoDO.
+ *
+ * @return InstanceInfoDO
+ */
+ public InstanceInfoDO build() {
+ InstanceInfoDO instanceInfoDO = new InstanceInfoDO();
+ instanceInfoDO.setId(id);
+ instanceInfoDO.setDateCreated(dateCreated);
+ instanceInfoDO.setDateUpdated(dateUpdated);
+ instanceInfoDO.setInstanceIp(instanceIp);
+ instanceInfoDO.setInstancePort(instancePort);
+ instanceInfoDO.setInstanceType(instanceType);
+ instanceInfoDO.setInstanceInfo(instanceInfo);
+ instanceInfoDO.setInstanceState(instanceState);
+ instanceInfoDO.setNamespaceId(namespaceId);
+ return instanceInfoDO;
+ }
+ }
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/InstanceQuery.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/InstanceQuery.java
new file mode 100644
index 0000000000..18768876b5
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/InstanceQuery.java
@@ -0,0 +1,202 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.model.query;
+
+import org.apache.shenyu.admin.model.page.PageParameter;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * this is instance query.
+ */
+public class InstanceQuery implements Serializable {
+
+ private static final long serialVersionUID = 6666008171280192709L;
+
+ /**
+ * id.
+ */
+ private String instanceId;
+
+ /**
+ * namespace id.
+ */
+ private String namespaceId;
+
+ /**
+ * instance type.
+ */
+ private String instanceType;
+
+ /**
+ * instance ip.
+ */
+ private String instanceIp;
+
+ /**
+ * instance port.
+ */
+ private String instancePort;
+
+ /**
+ * page parameter.
+ */
+ private PageParameter pageParameter;
+
+
+ public InstanceQuery() {
+ }
+
+ public InstanceQuery(final PageParameter pageParameter, final String
instanceType, final String instanceIp, final String instancePort, final String
namespaceId) {
+ this.instanceIp = instanceIp;
+ this.instancePort = instancePort;
+ this.namespaceId = namespaceId;
+ this.instanceType = instanceType;
+ this.pageParameter = pageParameter;
+ }
+
+ /**
+ * Gets the value of instanceId.
+ *
+ * @return the value of instanceId
+ */
+ public String getInstanceId() {
+ return instanceId;
+ }
+
+ /**
+ * Sets the instanceId.
+ *
+ * @param instanceId instanceId
+ */
+ public void setInstanceId(final String instanceId) {
+ this.instanceId = instanceId;
+ }
+
+ /**
+ * Gets the value of instanceType.
+ *
+ * @return the value of instanceType
+ */
+ public String getInstanceType() {
+ return instanceType;
+ }
+
+ /**
+ * Sets the instanceType.
+ *
+ * @param instanceType instanceType
+ */
+ public void setInstanceType(final String instanceType) {
+ this.instanceType = instanceType;
+ }
+
+ /**
+ * Gets the value of instanceIp.
+ *
+ * @return the value of instanceIp
+ */
+ public String getInstanceIp() {
+ return instanceIp;
+ }
+
+ /**
+ * Sets the instanceIp.
+ *
+ * @param instanceIp instanceIp
+ */
+ public void setInstanceIp(final String instanceIp) {
+ this.instanceIp = instanceIp;
+ }
+
+ /**
+ * Gets the value of instancePort.
+ *
+ * @return the value of instancePort
+ */
+ public String getInstancePort() {
+ return instancePort;
+ }
+
+ /**
+ * Sets the instancePort.
+ *
+ * @param instancePort instancePort
+ */
+ public void setInstancePort(final String instancePort) {
+ this.instancePort = instancePort;
+ }
+
+ /**
+ * Gets the value of name.
+ *
+ * @return the value of name
+ */
+ public String getNamespaceId() {
+ return namespaceId;
+ }
+
+ /**
+ * Sets the namespaceId.
+ *
+ * @param namespaceId namespaceId
+ */
+ public void setNamespaceId(final String namespaceId) {
+ this.namespaceId = namespaceId;
+ }
+
+ /**
+ * Gets the value of pageParameter.
+ *
+ * @return the value of pageParameter
+ */
+ public PageParameter getPageParameter() {
+ return pageParameter;
+ }
+
+ /**
+ * Sets the pageParameter.
+ *
+ * @param pageParameter pageParameter
+ */
+ public void setPageParameter(final PageParameter pageParameter) {
+ this.pageParameter = pageParameter;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (Objects.isNull(o) || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+ InstanceQuery that = (InstanceQuery) o;
+ return Objects.equals(namespaceId, that.namespaceId)
+ && Objects.equals(pageParameter, that.pageParameter);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), namespaceId, pageParameter);
+ }
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/InstanceQueryCondition.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/InstanceQueryCondition.java
new file mode 100644
index 0000000000..c5fb197874
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/query/InstanceQueryCondition.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.model.query;
+
+import
org.apache.shenyu.admin.model.page.condition.BaseExcludedSearchCondition;
+import org.apache.shenyu.admin.model.page.condition.SearchCondition;
+import org.apache.shenyu.admin.model.page.condition.SwitchCondition;
+
+/**
+ * this is instance query condition.
+ */
+public class InstanceQueryCondition extends BaseExcludedSearchCondition
implements SearchCondition, SwitchCondition {
+
+ /**
+ * search keyword: plugin name or role name.
+ */
+ private String keyword;
+
+ /**
+ * switch status: plugin status[close or open].
+ */
+ private Boolean switchStatus;
+
+ /**
+ * namespace id: namespaceId.
+ */
+ private String namespaceId;
+
+ /**
+ * Gets the value of name.
+ *
+ * @return the value of name
+ */
+ public String getNamespaceId() {
+ return namespaceId;
+ }
+
+ /**
+ * Sets the namespaceId.
+ *
+ * @param namespaceId namespaceId
+ */
+ public void setNamespaceId(final String namespaceId) {
+ this.namespaceId = namespaceId;
+ }
+
+
+ /**
+ * get switchStatus.
+ *
+ * @return status
+ */
+ @Override
+ public Boolean getSwitchStatus() {
+ return switchStatus;
+ }
+
+ /**
+ * set switchStatus.
+ *
+ * @param switchStatus status
+ */
+ public void setSwitchStatus(final Boolean switchStatus) {
+ this.switchStatus = switchStatus;
+ }
+
+ /**
+ * get keyword.
+ *
+ * @return keyword
+ */
+ @Override
+ public String getKeyword() {
+ return keyword;
+ }
+
+ /**
+ * set keyword.
+ *
+ * @param keyword keyword
+ */
+ @Override
+ public void setKeyword(final String keyword) {
+ this.keyword = keyword;
+ }
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java
new file mode 100644
index 0000000000..be41fe52b9
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/vo/InstanceInfoVO.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.model.vo;
+
+import java.io.Serializable;
+import java.sql.Timestamp;
+import java.util.Objects;
+
+/**
+ * InstanceInfoVO.
+ */
+public class InstanceInfoVO implements Serializable {
+
+ private static final long serialVersionUID = -5798225577222473005L;
+
+ /**
+ * instance ip.
+ */
+ private String instanceIp;
+
+ /**
+ * instance port.
+ */
+ private String instancePort;
+
+ /**
+ * instance type.
+ */
+ private String instanceType;
+
+ /**
+ * instance info.
+ */
+ private String instanceInfo;
+
+ /**
+ * namespaceId.
+ */
+ private String namespaceId;
+
+ /**
+ * created time.
+ */
+ private Timestamp dateCreated;
+
+ /**
+ * updated time.
+ */
+ private Timestamp dateUpdated;
+
+ /**
+ * get instanceIp.
+ *
+ * @return instanceIp
+ */
+ public String getInstanceIp() {
+ return instanceIp;
+ }
+
+ /**
+ * set instanceIp.
+ *
+ * @param instanceIp instanceIp
+ */
+ public void setInstanceIp(final String instanceIp) {
+ this.instanceIp = instanceIp;
+ }
+
+ /**
+ * get instancePort.
+ *
+ * @return instancePort
+ */
+ public String getInstancePort() {
+ return instancePort;
+ }
+
+ /**
+ * set instancePort.
+ *
+ * @param instancePort instancePort
+ */
+ public void setInstancePort(final String instancePort) {
+ this.instancePort = instancePort;
+ }
+
+ /**
+ * get instanceType.
+ *
+ * @return instanceType
+ */
+ public String getInstanceType() {
+ return instanceType;
+ }
+
+ /**
+ * set instanceType.
+ *
+ * @param instanceType instanceType
+ */
+ public void setInstanceType(final String instanceType) {
+ this.instanceType = instanceType;
+ }
+
+ /**
+ * get instanceInfo.
+ *
+ * @return instanceInfo
+ */
+ public String getInstanceInfo() {
+ return instanceInfo;
+ }
+
+ /**
+ * set instanceInfo.
+ *
+ * @param instanceInfo instanceInfo
+ */
+ public void setInstanceInfo(final String instanceInfo) {
+ this.instanceInfo = instanceInfo;
+ }
+
+ /**
+ * get namespaceId.
+ *
+ * @return namespaceId
+ */
+ public String getNamespaceId() {
+ return namespaceId;
+ }
+
+ /**
+ * set namespaceId.
+ *
+ * @param namespaceId namespaceId
+ */
+ public void setNamespaceId(final String namespaceId) {
+ this.namespaceId = namespaceId;
+ }
+
+ /**
+ * get dateCreated.
+ *
+ * @return dateCreated
+ */
+ public Timestamp getDateCreated() {
+ return dateCreated;
+ }
+
+ /**
+ * set dateCreated.
+ *
+ * @param dateCreated dateCreated
+ */
+ public void setDateCreated(final Timestamp dateCreated) {
+ this.dateCreated = dateCreated;
+ }
+
+ /**
+ * get dateUpdated.
+ *
+ * @return dateUpdated
+ */
+ public Timestamp getDateUpdated() {
+ return dateUpdated;
+ }
+
+ /**
+ * set dateUpdated.
+ *
+ * @param dateUpdated dateUpdated
+ */
+ public void setDateUpdated(final Timestamp dateUpdated) {
+ this.dateUpdated = dateUpdated;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (Objects.isNull(o) || getClass() != o.getClass()) {
+ return false;
+ }
+
+ InstanceInfoVO that = (InstanceInfoVO) o;
+ return Objects.equals(instanceIp, that.instanceIp)
+ && Objects.equals(instancePort, that.instancePort)
+ && Objects.equals(instanceType, that.instanceType)
+ && Objects.equals(instanceInfo, that.instanceInfo)
+ && Objects.equals(namespaceId, that.namespaceId)
+ && Objects.equals(dateCreated, that.dateCreated)
+ && Objects.equals(dateUpdated, that.dateUpdated);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(instanceIp, instancePort, instanceType,
instanceInfo, namespaceId, dateCreated, dateUpdated);
+ }
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java
new file mode 100644
index 0000000000..78cbb09d56
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/InstanceInfoService.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.service;
+
+import org.apache.shenyu.admin.model.dto.InstanceInfoDTO;
+import org.apache.shenyu.admin.model.page.CommonPager;
+import org.apache.shenyu.admin.model.query.InstanceQuery;
+import org.apache.shenyu.admin.model.query.InstanceQueryCondition;
+import org.apache.shenyu.admin.model.vo.InstanceInfoVO;
+
+public interface InstanceInfoService extends
PageService<InstanceQueryCondition, InstanceInfoVO> {
+
+ /**
+ * Creates or updates an instance information record.
+ *
+ * @param instanceInfoDTO the instance information data transfer object
+ */
+ void createOrUpdate(InstanceInfoDTO instanceInfoDTO);
+
+ /**
+ * List instance info by page.
+ *
+ * @param instanceQuery instanceQuery
+ * @return CommonPager
+ */
+ CommonPager<InstanceInfoVO> listByPage(InstanceQuery instanceQuery);
+
+ /**
+ * findById.
+ * @param id instance id
+ * @return InstanceInfoVO
+ */
+ InstanceInfoVO findById(String id);
+
+}
diff --git
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java
new file mode 100644
index 0000000000..4c13b9081e
--- /dev/null
+++
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/InstanceInfoServiceImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.admin.service.impl;
+
+import org.apache.shenyu.admin.mapper.InstanceInfoMapper;
+import org.apache.shenyu.admin.model.dto.InstanceInfoDTO;
+import org.apache.shenyu.admin.model.entity.InstanceInfoDO;
+import org.apache.shenyu.admin.model.page.CommonPager;
+import org.apache.shenyu.admin.model.page.PageResultUtils;
+import org.apache.shenyu.admin.model.query.InstanceQuery;
+import org.apache.shenyu.admin.model.vo.InstanceInfoVO;
+import org.apache.shenyu.admin.service.InstanceInfoService;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Implementation of the {@link
org.apache.shenyu.admin.service.InstanceInfoService}.
+ */
+@Service
+public class InstanceInfoServiceImpl implements InstanceInfoService {
+
+ private static final Logger LOG =
LoggerFactory.getLogger(InstanceInfoServiceImpl.class);
+
+ private final InstanceInfoMapper instanceInfoMapper;
+
+ public InstanceInfoServiceImpl(final InstanceInfoMapper
instanceInfoMapper) {
+ this.instanceInfoMapper = instanceInfoMapper;
+ }
+
+ @Override
+ public void createOrUpdate(final InstanceInfoDTO instanceInfoDTO) {
+ InstanceQuery instanceQuery = new InstanceQuery();
+ instanceQuery.setInstanceIp(instanceInfoDTO.getInstanceIp());
+ instanceQuery.setInstancePort(instanceInfoDTO.getInstancePort());
+ instanceQuery.setInstanceType(instanceInfoDTO.getInstanceType());
+ instanceQuery.setNamespaceId(instanceInfoDTO.getNamespaceId());
+ InstanceInfoDO infoDO =
instanceInfoMapper.selectOneByQuery(instanceQuery);
+ if (Objects.isNull(infoDO)) {
+ LOG.info("Register new instance info: {}",
GsonUtils.getInstance().toJson(instanceInfoDTO));
+ InstanceInfoDO instanceInfoDO =
InstanceInfoDO.buildInstanceInfoDO(instanceInfoDTO);
+ try {
+ instanceInfoMapper.insert(instanceInfoDO);
+ } catch (Exception e) {
+ LOG.error("Failed to register instance info", e);
+ }
+ return;
+ }
+ LOG.info("Update instance info: {}",
GsonUtils.getInstance().toJson(instanceInfoDTO));
+ infoDO.setInstanceIp(instanceInfoDTO.getInstanceIp());
+ infoDO.setInstanceType(instanceInfoDTO.getInstanceType());
+ infoDO.setInstanceInfo(instanceInfoDTO.getInstanceInfo());
+ infoDO.setNamespaceId(instanceInfoDTO.getNamespaceId());
+ infoDO.setDateUpdated(Timestamp.from(Instant.now()));
+ infoDO.setInstanceState(instanceInfoDTO.getInstanceState());
+ instanceInfoMapper.updateById(infoDO);
+ }
+
+ @Override
+ public CommonPager<InstanceInfoVO> listByPage(final InstanceQuery
instanceQuery) {
+ List<InstanceInfoDO> instanceInfoDOList =
instanceInfoMapper.selectByQuery(instanceQuery);
+ return PageResultUtils.result(instanceQuery.getPageParameter(), () ->
this.buildInstanceInfoVO(instanceInfoDOList));
+ }
+
+ @Override
+ public InstanceInfoVO findById(final String id) {
+ return null;
+ }
+
+ private List<InstanceInfoVO> buildInstanceInfoVO(final
List<InstanceInfoDO> instanceInfoDOList) {
+ if (instanceInfoDOList.isEmpty()) {
+ return List.of();
+ }
+ return instanceInfoDOList.stream()
+ .map(this::buildInstanceInfoVO)
+ .toList();
+ }
+
+ private InstanceInfoVO buildInstanceInfoVO(final InstanceInfoDO
instanceInfoDO) {
+ InstanceInfoVO instanceInfoVO = new InstanceInfoVO();
+ instanceInfoVO.setInstanceIp(instanceInfoDO.getInstanceIp());
+ instanceInfoVO.setInstancePort(instanceInfoDO.getInstancePort());
+ instanceInfoVO.setInstanceType(instanceInfoDO.getInstanceType());
+ instanceInfoVO.setInstanceInfo(instanceInfoDO.getInstanceInfo());
+ instanceInfoVO.setNamespaceId(instanceInfoDO.getNamespaceId());
+ instanceInfoVO.setDateCreated(instanceInfoDO.getDateCreated());
+ instanceInfoVO.setDateUpdated(instanceInfoDO.getDateUpdated());
+ return instanceInfoVO;
+ }
+}
diff --git a/shenyu-admin/src/main/resources/application-mysql.yml
b/shenyu-admin/src/main/resources/application-mysql.yml
index 73c9a817a1..6db63a81d1 100755
--- a/shenyu-admin/src/main/resources/application-mysql.yml
+++ b/shenyu-admin/src/main/resources/application-mysql.yml
@@ -22,7 +22,7 @@ spring:
datasource:
url:
jdbc:mysql://localhost:3306/shenyu?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&zeroDateTimeBehavior=convertToNull&allowPublicKeyRetrieval=true
username: root
- password: 12345678
+ password: passwd4mysql
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
connection-timeout: 30000
diff --git a/shenyu-admin/src/main/resources/application.yml
b/shenyu-admin/src/main/resources/application.yml
index 7a42448b22..f066cc6068 100755
--- a/shenyu-admin/src/main/resources/application.yml
+++ b/shenyu-admin/src/main/resources/application.yml
@@ -21,7 +21,7 @@ spring:
application:
name: shenyu-admin
profiles:
- active: h2
+ active: mysql
thymeleaf:
cache: true
encoding: utf-8
diff --git a/shenyu-admin/src/main/resources/mappers/instance-info-sqlmap.xml
b/shenyu-admin/src/main/resources/mappers/instance-info-sqlmap.xml
new file mode 100644
index 0000000000..d2a112b9ef
--- /dev/null
+++ b/shenyu-admin/src/main/resources/mappers/instance-info-sqlmap.xml
@@ -0,0 +1,154 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="org.apache.shenyu.admin.mapper.InstanceInfoMapper">
+ <resultMap id="BaseResultMap"
type="org.apache.shenyu.admin.model.entity.InstanceInfoDO">
+ <id column="id" jdbcType="VARCHAR" property="id"/>
+ <result column="date_created" jdbcType="TIMESTAMP"
property="dateCreated"/>
+ <result column="date_updated" jdbcType="TIMESTAMP"
property="dateUpdated"/>
+ <result column="instance_ip" jdbcType="VARCHAR" property="instanceIp"/>
+ <result column="instance_port" jdbcType="VARCHAR"
property="instancePort"/>
+ <result column="instance_type" jdbcType="VARCHAR"
property="instanceType"/>
+ <result column="instance_info" jdbcType="VARCHAR"
property="instanceInfo"/>
+ <result column="namespace_id" jdbcType="VARCHAR"
property="namespaceId"/>
+ </resultMap>
+
+ <sql id="Base_Column_List">
+ id,
+ date_created,
+ date_updated,
+ instance_ip,
+ instance_port,
+ instance_type,
+ instance_info,
+ instance_state,
+ namespace_id,
+ date_created,
+ date_updated
+ </sql>
+
+ <update id="updateById">
+ UPDATE
+ instance_info
+ SET
+ date_updated = #{dateUpdated, jdbcType=TIMESTAMP},
+ instance_ip = #{instanceIp, jdbcType=VARCHAR},
+ instance_port = #{instancePort, jdbcType=VARCHAR},
+ instance_type = #{instanceType, jdbcType=VARCHAR},
+ instance_info = #{instanceInfo, jdbcType=VARCHAR},
+ instance_state = #{instanceState, jdbcType=TINYINT}
+ WHERE
+ id = #{id, jdbcType=VARCHAR}
+ </update>
+
+ <select id="findAllByNamespaceId" resultMap="BaseResultMap">
+ SElECT
+ <include refid="Base_Column_List"/>
+ FROM instance_info
+ WHERE namespace_id = #{namespaceId, jdbcType=VARCHAR}
+ </select>
+
+ <select id="selectAll" resultMap="BaseResultMap">
+ SElECT
+ <include refid="Base_Column_List"/>
+ FROM instance_info
+ </select>
+
+ <select id="existed" resultType="java.lang.Boolean">
+ SElECT true
+ FROM instance_info
+ WHERE id = #{id}
+ LIMIT 1
+ </select>
+
+ <select id="selectByQuery" resultMap="BaseResultMap">
+ SElECT
+ <include refid="Base_Column_List"/>
+ FROM instance_info
+ WHERE namespace_id = #{namespaceId}
+ <if test="instanceIp != null and instanceIp != ''">
+ AND instance_ip like CONCAT('%', #{instanceIp}, '%')
+ </if>
+ <if test="instancePort != null and instancePort != ''">
+ AND instance_port = #{instancePort}
+ </if>
+ <if test="instanceType != null and instanceType != ''">
+ AND instance_type = #{instanceType}
+ </if>
+ </select>
+
+ <select id="selectById"
resultType="org.apache.shenyu.admin.model.entity.InstanceInfoDO">
+ SElECT
+ <include refid="Base_Column_List"/>
+ FROM instance_info
+ WHERE id = #{id}
+ </select>
+
+ <select id="selectOneByQuery"
resultType="org.apache.shenyu.admin.model.entity.InstanceInfoDO">
+ SElECT
+ <include refid="Base_Column_List"/>
+ FROM instance_info
+ WHERE 1=1
+ <if test="instanceIp != null and instanceIp != ''">
+ AND instance_ip = #{instanceIp}
+ </if>
+ <if test="namespaceId != null and namespaceId != ''">
+ AND namespace_id = #{namespaceId}
+ </if>
+ <if test="instancePort != null and instancePort != ''">
+ AND instance_port = #{instancePort}
+ </if>
+ <if test="instanceType != null and instanceType != ''">
+ AND instance_type = #{instanceType}
+ </if>
+ <if test="instanceId != null and instanceId != ''">
+ AND id = #{instanceId}
+ </if>
+ LIMIT 1
+ </select>
+
+ <insert id="insert"
parameterType="org.apache.shenyu.admin.model.entity.InstanceInfoDO">
+ INSERT INTO instance_info
+ (id,
+ date_created,
+ date_updated,
+ instance_ip,
+ instance_port,
+ instance_type,
+ instance_info,
+ instance_state,
+ namespace_id)
+ VALUES
+ (#{id,jdbcType=VARCHAR},
+ #{dateCreated,jdbcType=TIMESTAMP},
+ #{dateUpdated,jdbcType=TIMESTAMP},
+ #{instanceIp,jdbcType=VARCHAR},
+ #{instancePort,jdbcType=VARCHAR},
+ #{instanceType,jdbcType=VARCHAR},
+ #{instanceInfo,jdbcType=VARCHAR},
+ #{instanceState,jdbcType=TINYINT},
+ #{namespaceId,jdbcType=VARCHAR})
+ </insert>
+
+ <delete id="delete" parameterType="java.lang.String">
+ DELETE FROM instance_info
+ WHERE id = #{id,jdbcType=VARCHAR}
+ </delete>
+
+</mapper>
diff --git a/shenyu-admin/src/main/resources/mappers/meta-data-sqlmap.xml
b/shenyu-admin/src/main/resources/mappers/meta-data-sqlmap.xml
index 6f73e725d7..9093a3a920 100644
--- a/shenyu-admin/src/main/resources/mappers/meta-data-sqlmap.xml
+++ b/shenyu-admin/src/main/resources/mappers/meta-data-sqlmap.xml
@@ -46,7 +46,6 @@
method_name,
parameter_types,
rpc_ext,
- namespace_id,
enabled,
namespace_id
</sql>
diff --git a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
index 91b7747646..6a85875313 100644
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -1031,6 +1031,13 @@ INSERT IGNORE INTO `resource` (`id`, `parent_id`,
`title`, `name`, `url`, `compo
INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1347049731047698432','1346778036402483200','SHENYU.BUTTON.SYSTEM.ENABLE','','','','2','3','','1','0','system:dict:disable','1');
INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1347049794008395776','1346778036402483200','SHENYU.BUTTON.SYSTEM.EDIT','','','','2','4','','1','0','system:dict:edit','1');
+INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483300','1357956838021890048','SHENYU.MENU.SYSTEM.MANAGMENT.INSTANCE','instance','/config/instance','instance','1','6','ordered-list','0','0','','1');
+INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483301','1346778036402483300','SHENYU.BUTTON.SYSTEM.LIST','','','','2','0','','1','0','system:instance:list','1');
+INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483302','1346778036402483300','SHENYU.BUTTON.SYSTEM.DELETE','','','','2','1','','1','0','system:instance:delete','1');
+INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483303','1346778036402483300','SHENYU.BUTTON.SYSTEM.ADD','','','','2','2','','1','0','system:instance:add','1');
+INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483304','1346778036402483300','SHENYU.BUTTON.SYSTEM.ENABLE','','','','2','3','','1','0','system:instance:disable','1');
+INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346778036402483305','1346778036402483300','SHENYU.BUTTON.SYSTEM.EDIT','','','','2','4','','1','0','system:instance:edit','1');
+
INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346776175553376256','','SHENYU.MENU.SYSTEM.MANAGMENT','system','/system','system','0','2','setting','0','0','','1');
INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1346777157943259136','1346776175553376256','SHENYU.MENU.SYSTEM.MANAGMENT.USER','manage','/system/manage','manage','1','1','user','0','0','','1');
INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`,
`component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`,
`status`)
VALUES('1347032308726902784','1346777157943259136','SHENYU.BUTTON.SYSTEM.ADD','','','','2','0','','1','0','system:manager:add','1');
@@ -1495,3 +1502,24 @@ CREATE TABLE IF NOT EXISTS `namespace_user_rel`
PRIMARY KEY (`id`)
);
+CREATE TABLE IF NOT EXISTS instance_info
+(
+ `id` varchar(128) NOT NULL COMMENT 'primary key',
+ `namespace_id` varchar(50) NOT NULL COMMENT 'namespace_id',
+ `instance_ip` varchar(128) NOT NULL COMMENT 'instance_ip',
+ `instance_port` varchar(128) NOT NULL COMMENT 'instance_port',
+ `instance_type` varchar(128) NOT NULL COMMENT 'instance_type',
+ `instance_info` text NOT NULL COMMENT 'instance_info',
+ `instance_state` int NOT NULL COMMENT '0-unknown 1-online 2-offline',
+ `date_created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT
'date_created',
+ `date_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE
CURRENT_TIMESTAMP COMMENT 'date_updated',
+ PRIMARY KEY (`id`)
+);
+
+
+INSERT IGNORE INTO `permission` (`id`, `object_id`, `resource_id`,
`date_created`, `date_updated`) VALUES ('1697141926281382720',
'1346358560427216896', '1346778036402483300', '2023-08-31 06:59:01',
'2023-08-31 06:59:01');
+INSERT IGNORE INTO `permission` (`id`, `object_id`, `resource_id`,
`date_created`, `date_updated`) VALUES ('1697141926281382721',
'1346358560427216896', '1346778036402483301', '2023-08-31 07:22:07',
'2023-08-31 07:22:07');
+INSERT IGNORE INTO `permission` (`id`, `object_id`, `resource_id`,
`date_created`, `date_updated`) VALUES ('1697141926281382722',
'1346358560427216896', '1346778036402483302', '2023-08-31 07:14:26',
'2023-08-31 07:14:26');
+INSERT IGNORE INTO `permission` (`id`, `object_id`, `resource_id`,
`date_created`, `date_updated`) VALUES ('1697141926281382723',
'1346358560427216896', '1346778036402483303', '2023-08-31 07:22:07',
'2023-08-31 07:22:07');
+INSERT IGNORE INTO `permission` (`id`, `object_id`, `resource_id`,
`date_created`, `date_updated`) VALUES ('1697141926281382724',
'1346358560427216896', '1346778036402483304', '2023-08-31 07:18:37',
'2023-08-31 07:18:37');
+INSERT IGNORE INTO `permission` (`id`, `object_id`, `resource_id`,
`date_created`, `date_updated`) VALUES ('1697141926281382725',
'1346358560427216896', '1346778036402483305', '2023-08-31 07:18:37',
'2023-08-31 07:18:37');
diff --git
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java
index c7d1270447..6fa228dc88 100644
---
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java
+++
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/disruptor/subcriber/ShenyuClientURIExecutorSubscriber.java
@@ -63,13 +63,7 @@ public class ShenyuClientURIExecutorSubscriber implements
ExecutorTypeSubscriber
ThreadFactory requestFactory =
ShenyuThreadFactory.create("heartbeat-reporter", true);
executor = new ScheduledThreadPoolExecutor(1, requestFactory);
- executor.scheduleAtFixedRate(() -> {
- try {
- URIS.forEach(this::sendHeartbeat);
- } catch (Exception e) {
- LOG.error("send heartbeat error", e);
- }
- }, 30, 30, TimeUnit.SECONDS);
+ executor.scheduleAtFixedRate(() -> URIS.forEach(this::sendHeartbeat),
30, 30, TimeUnit.SECONDS);
}
@Override
diff --git a/shenyu-common/pom.xml b/shenyu-common/pom.xml
index 9d6e1dd8c6..8770011424 100644
--- a/shenyu-common/pom.xml
+++ b/shenyu-common/pom.xml
@@ -88,5 +88,12 @@
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk18on</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>com.github.oshi</groupId>
+ <artifactId>oshi-core</artifactId>
+ <version>6.7.0</version>
+ </dependency>
+
</dependencies>
</project>
diff --git
a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/type/DataType.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/InstanceTypeConstants.java
similarity index 60%
copy from
shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/type/DataType.java
copy to
shenyu-common/src/main/java/org/apache/shenyu/common/constant/InstanceTypeConstants.java
index b539219621..2c75a1636b 100644
---
a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/type/DataType.java
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/InstanceTypeConstants.java
@@ -15,35 +15,31 @@
* limitations under the License.
*/
-package org.apache.shenyu.register.common.type;
+package org.apache.shenyu.common.constant;
/**
- * The enum Data type enum.
+ * instance type constants.
*/
-public enum DataType {
+public class InstanceTypeConstants {
/**
- * Meta data data type enum.
+ * The constant bootstrapInstanceInfo.
*/
- META_DATA,
+ public static final String BOOTSTRAP_INSTANCE_INFO =
"bootstrapInstanceInfo";
/**
- * Uri data type enum.
+ * The constant clientInstanceInfo.
*/
- URI,
-
- /**
- * Api doc type enum.
- */
- API_DOC,
-
+ public static final String CLIENT_INSTANCE_INFO = "clientInstanceInfo";
+
/**
- * Heartbeat type enum.
+ * The constant bootstrapInstanceType.
*/
- HEARTBEAT,
-
+ public static final String BOOTSTRAP_INSTANCE_TYPE = "bootstrap";
+
/**
- * Discovery config type enum.
+ * The constant clientInstanceInfo.
*/
- DISCOVERY_CONFIG,
+ public static final String CLIENT_INSTANCE_TYPE = "client";
+
}
diff --git
a/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java
b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java
new file mode 100644
index 0000000000..b137abc440
--- /dev/null
+++
b/shenyu-common/src/main/java/org/apache/shenyu/common/utils/SystemInfoUtils.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.utils;
+
+import com.sun.management.OperatingSystemMXBean;
+import oshi.SystemInfo;
+
+import java.lang.management.ManagementFactory;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.Map;
+
+/**
+ * The type System info utils.
+ */
+public final class SystemInfoUtils {
+
+ /**
+ * Gets system info.
+ *
+ * @return the system info
+ */
+ public static String getSystemInfo() {
+ try {
+ // Get host information using OSHI
+ SystemInfo systemInfo = new SystemInfo();
+
+ // Get host information
+ OperatingSystemMXBean osBean =
+ (OperatingSystemMXBean)
ManagementFactory.getOperatingSystemMXBean();
+ Map<String, Object> hostInfo = Map.of(
+ "arch", osBean.getArch(),
+ "operatingSystem",
systemInfo.getOperatingSystem().toString(),
+ "availableProcessors", osBean.getAvailableProcessors(),
+ "totalMemorySizeGB",
bytesToGB(osBean.getTotalMemorySize()) + " GB"
+ );
+ return GsonUtils.getInstance().toJson(hostInfo);
+ } catch (Exception e) {
+ // Handle any exceptions that may occur
+ return "Error retrieving system information: " + e.getMessage();
+ }
+ }
+
+ /**
+ * Bytes to gb double.
+ *
+ * @param bytesValue the bytes value
+ * @return the double
+ */
+ private static double bytesToGB(final long bytesValue) {
+ return BigDecimal.valueOf(bytesValue / (1024.0 * 1024 *
1024)).setScale(2, RoundingMode.HALF_UP).doubleValue();
+ }
+}
diff --git
a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/type/DataType.java
b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/type/DataType.java
index b539219621..ff1002a4dc 100644
---
a/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/type/DataType.java
+++
b/shenyu-register-center/shenyu-register-common/src/main/java/org/apache/shenyu/register/common/type/DataType.java
@@ -46,4 +46,9 @@ public enum DataType {
* Discovery config type enum.
*/
DISCOVERY_CONFIG,
+
+ /**
+ * Instance info type enum.
+ */
+ INSTANCE_INFO,
}