This is an automated email from the ASF dual-hosted git repository.

chenwenkang 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 0af754d949 [feat] sofa plugin config based on selector (#6062)
0af754d949 is described below

commit 0af754d949c7e4851ab6c62f78750b50cfd981fe
Author: Yu Siheng <[email protected]>
AuthorDate: Sun Sep 28 09:23:05 2025 +0800

    [feat] sofa plugin config based on selector (#6062)
    
    * [feat] sofa plugin config based on selector
    
    * fix
    
    * add test file
    
    * fix
    
    ---------
    
    Co-authored-by: aias00 <[email protected]>
    Co-authored-by: loongs-zhang <[email protected]>
    Co-authored-by: Misaya295 <[email protected]>
---
 db/init/mysql/schema.sql                           |   2 +
 db/init/ob/schema.sql                              |   2 +
 db/init/og/create-table.sql                        |   2 +
 db/init/oracle/schema.sql                          |   7 +-
 db/init/pg/create-table.sql                        |   2 +
 db/upgrade/2.7.0-upgrade-2.7.1-mysql.sql           |   7 +
 db/upgrade/2.7.0-upgrade-2.7.1-ob.sql              |   9 +-
 db/upgrade/2.7.0-upgrade-2.7.1-og.sql              |   7 +-
 db/upgrade/2.7.0-upgrade-2.7.1-oracle.sql          |  16 +
 db/upgrade/2.7.0-upgrade-2.7.1-pg.sql              |   9 +
 .../src/main/resources/sql-script/h2/schema.sql    |   2 +
 .../apache/shenyu/common/constant/Constants.java   |   5 +
 .../common/dto/convert/selector/SofaUpstream.java  | 347 +++++++++++++++++++++
 .../org/apache/shenyu/plugin/sofa/SofaPlugin.java  |   2 +-
 .../plugin/sofa/cache/ApplicationConfigCache.java  | 221 ++++++++++++-
 .../plugin/sofa/handler/SofaMetaDataHandler.java   |   4 +-
 .../plugin/sofa/handler/SofaPluginDataHandler.java |  21 ++
 .../shenyu/plugin/sofa/proxy/SofaProxyService.java |  42 ++-
 .../apache/shenyu/plugin/sofa/SofaPluginTest.java  |   4 +-
 .../sofa/cache/ApplicationConfigCacheTest.java     |  97 ++++++
 .../plugin/sofa/proxy/SofaProxyServiceTest.java    |  63 +++-
 21 files changed, 832 insertions(+), 39 deletions(-)

diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql
index 52bbf64c28..04de9d6c7e 100644
--- a/db/init/mysql/schema.sql
+++ b/db/init/mysql/schema.sql
@@ -1082,6 +1082,8 @@ INSERT INTO `plugin_handle` VALUES 
('1529402613199978532', '4', 'url', 'url', 2,
 INSERT INTO `plugin_handle` VALUES ('1529402613199978533', '4', 'password', 
'password', 2, 3, 4, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978534', '11', 'protocol', 
'protocol', 2, 3, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978535', '11', 'register', 
'register', 2, 3, 2, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613199978534', '11', 'protocol', 
'protocol', 2, 1, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613199978535', '11', 'register', 
'register', 2, 1, 2, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978536', '2', 'model', 
'model', 2, 3, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978537', '6', 'register', 
'register', 2, 3, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978538', '4', 
'algorithmName', 'algorithmName', 3, 2, 1, 
'{\"required\":\"1\",\"defaultValue\":\"slidingWindow\",\"rule\":\"\"}', 
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
diff --git a/db/init/ob/schema.sql b/db/init/ob/schema.sql
index 70ad567a22..1ab5c38184 100644
--- a/db/init/ob/schema.sql
+++ b/db/init/ob/schema.sql
@@ -1049,6 +1049,8 @@ INSERT INTO `plugin_handle` VALUES 
('1529402613199978532', '4', 'url', 'url', 2,
 INSERT INTO `plugin_handle` VALUES ('1529402613199978533', '4', 'password', 
'password', 2, 3, 4, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978534', '11', 'protocol', 
'protocol', 2, 3, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978535', '11', 'register', 
'register', 2, 3, 2, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613199978534', '11', 'protocol', 
'protocol', 2, 1, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613199978535', '11', 'register', 
'register', 2, 1, 2, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978536', '2', 'model', 
'model', 2, 3, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978537', '6', 'register', 
'register', 2, 3, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1529402613199978538', '4', 
'algorithmName', 'algorithmName', 3, 2, 1, 
'{\"required\":\"1\",\"defaultValue\":\"slidingWindow\",\"rule\":\"\"}', 
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
diff --git a/db/init/og/create-table.sql b/db/init/og/create-table.sql
index 9802802a61..152aef1c1e 100644
--- a/db/init/og/create-table.sql
+++ b/db/init/og/create-table.sql
@@ -1070,6 +1070,8 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1529403902775136287', '4', 'url',
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136288', '4', 
'password', 'password', 2, 3, 4, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136289', '11', 
'protocol', 'protocol', 2, 3, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136290', '11', 
'register', 'register', 2, 3, 2, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136289', '11', 
'protocol', 'protocol', 2, 1, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136290', '11', 
'register', 'register', 2, 1, 2, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136291', '2', 
'model', 'model', 2, 3, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136292', '6', 
'register', 'register', 2, 3, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136293', '4', 
'algorithmName', 'algorithmName', 3, 2, 1, 
'{"required":"1","defaultValue":"slidingWindow","rule":""}', '2022-05-25 
18:08:01', '2022-05-25 18:08:01');
diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql
index 04c74d20ab..8ddb8c4ec8 100644
--- a/db/init/oracle/schema.sql
+++ b/db/init/oracle/schema.sql
@@ -1533,6 +1533,12 @@ values ('1518229897210273825', '11', 'protocol', 
'protocol', 2, 3, 1, null);
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1518229897210273826', '11', 'register', 'register', 2, 3, 2, null);
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897210273825', '11', 'protocol', 'protocol', 2, 1, 1, null);
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897210273826', '11', 'register', 'register', 2, 1, 2, null);
+
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1518229897210273827', '2', 'model', 'model', 2, 3, 1, null);
 
@@ -1722,7 +1728,6 @@ values ('1518229897214468166', '11', 'queues', 'queues', 
1, 3, 6, '{"required":"
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1518229897214468167', '11', 'threadpool', 'threadpool', 3, 3, 3, 
'{"required":"0","defaultValue":"default","placeholder":"threadpool","rule":""}');
 
-
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1537326008606343168', '31', 'responseContent', 'responseContent', 2, 
2, 0, '{"required":"0","rule":""}');
 
diff --git a/db/init/pg/create-table.sql b/db/init/pg/create-table.sql
index 5cf29cce8f..db76279d5a 100644
--- a/db/init/pg/create-table.sql
+++ b/db/init/pg/create-table.sql
@@ -1128,6 +1128,8 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1529403902775136287', '4', 'url',
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136288', '4', 
'password', 'password', 2, 3, 4, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136289', '11', 
'protocol', 'protocol', 2, 3, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136290', '11', 
'register', 'register', 2, 3, 2, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136289', '11', 
'protocol', 'protocol', 2, 1, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136290', '11', 
'register', 'register', 2, 1, 2, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136291', '2', 
'model', 'model', 2, 3, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136292', '6', 
'register', 'register', 2, 3, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1529403902775136293', '4', 
'algorithmName', 'algorithmName', 3, 2, 1, 
'{"required":"1","defaultValue":"slidingWindow","rule":""}', '2022-05-25 
18:08:01', '2022-05-25 18:08:01');
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 12aca0b15a..efa82bc12e 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
@@ -265,6 +265,13 @@ INSERT INTO `plugin_handle` VALUES ('1907263843073671168', 
'61', 'description',
 INSERT INTO `plugin_handle` VALUES ('1529402613204173925', '6', 'registry', 
'registry', 2, 1, 0, '{\"required\":\"0\",\"rule\":\"\"}', '2025-02-27 
17:20:50.233', '2025-02-27 17:20:50.233');
 UPDATE `plugin_handle` SET ext_obj = '{\"required\":\"0\",\"rule\":\"\"}' 
WHERE plugin_id = '6' AND label = 'ip:port' AND data_type = 2;
 
+INSERT INTO `plugin_handle` VALUES ('1529402613199978534', '11', 'protocol', 
'protocol', 2, 1, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1529402613199978535', '11', 'register', 
'register', 2, 1, 2, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172874', '11', 
'corethreads', 'corethreads', 1, 1, 4, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"corethreads\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172875', '11', 'threads', 
'threads', 1, 1, 5, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"threads\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172876', '11', 'queues', 
'queues', 1, 1, 6, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"queues\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1529402613204172877', '11', 'threadpool', 
'threadpool', 3, 1, 3, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"threadpool\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+
 INSERT INTO `plugin_handle` VALUES ('1829402613204172834', '17', 
'registerProtocol', 'registerProtocol', 2, 1, 0, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"registerProtocol\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1829402613204172835', '17', 
'corethreads', 'corethreads', 1, 1, 2, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"corethreads\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1829402613204172836', '17', 'threads', 
'threads', 1, 1, 3, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"threads\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
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 70257bcd8a..69e7031f48 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
@@ -232,6 +232,12 @@ INSERT INTO `permission` VALUES ('1697146860569742760', 
'1346358560427216896', '
 INSERT INTO `plugin_handle` VALUES ('1529402613204173925', '6', 'registry', 
'registry', 2, 1, 0, '{\"required\":\"0\",\"rule\":\"\"}', '2025-02-27 
17:20:50.233', '2025-02-27 17:20:50.233');
 UPDATE `plugin_handle` SET ext_obj = '{\"required\":\"0\",\"rule\":\"\"}' 
WHERE plugin_id = '6' AND label = 'ip:port' AND data_type = 2;
 
+INSERT INTO `plugin_handle` VALUES ('1729402613199978534', '11', 'protocol', 
'protocol', 2, 1, 1, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613199978535', '11', 'register', 
'register', 2, 1, 2, NULL, '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613204172874', '11', 
'corethreads', 'corethreads', 1, 1, 4, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"corethreads\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613204172875', '11', 'threads', 
'threads', 1, 1, 5, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"threads\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613204172876', '11', 'queues', 
'queues', 1, 1, 6, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"queues\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
+INSERT INTO `plugin_handle` VALUES ('1729402613204172877', '11', 'threadpool', 
'threadpool', 3, 1, 3, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"threadpool\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 
 INSERT INTO `plugin_handle` VALUES ('1829402613204172834', '17', 
'registerProtocol', 'registerProtocol', 2, 1, 0, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"registerProtocol\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO `plugin_handle` VALUES ('1829402613204172835', '17', 
'corethreads', 'corethreads', 1, 1, 2, 
'{\"required\":\"0\",\"defaultValue\":\"\",\"placeholder\":\"corethreads\",\"rule\":\"\"}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
@@ -300,10 +306,11 @@ ALTER TABLE `selector` CHANGE COLUMN `sort` `sort_code` 
int(0) NOT NULL COMMENT
 ALTER TABLE `selector` CHANGE COLUMN `name` `selector_name` varchar(64) 
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'selector 
name';
 ALTER TABLE `tag` CHANGE COLUMN `name` `tag_name` varchar(128) CHARACTER SET 
utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'tag name';
 ALTER TABLE `rule` CHANGE COLUMN `sort` `sort_code` int(0) NOT NULL COMMENT 
'sort';
+
 ALTER TABLE `rule` CHANGE COLUMN `name` `rule_name` varchar(128) CHARACTER SET 
utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'rule name';
 ALTER TABLE `discovery` CHANGE COLUMN `type` `discovery_type` int(0) NOT NULL 
COMMENT 'discovery type';
 ALTER TABLE `discovery` CHANGE COLUMN `name` `discovery_name` varchar(128) 
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'discovery 
name';
 ALTER TABLE `discovery_upstream` CHANGE COLUMN `url` `upstream_url` 
varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 
'ip:port';
 ALTER TABLE `discovery_upstream` CHANGE COLUMN `status` `upstream_status` 
int(0) NOT NULL COMMENT 'type (0, healthy, 1 unhealthy)';
 
-ALTER TABLE `discovery` CHANGE COLUMN `level` `discovery_level` varchar(64) 
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '0 selector,1 
plugin  2 global';
+ALTER TABLE `discovery` CHANGE COLUMN `level` `discovery_level` varchar(64) 
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '0 selector,1 
plugin  2 global';
\ No newline at end of file
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 72c6391fc6..5ddf379df8 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
@@ -247,6 +247,12 @@ INSERT INTO "public"."permission" VALUES 
('1697146860569742760', '13463585604272
 INSERT INTO "public"."plugin_handle" VALUES ('1529402613204173925', '6', 
'registry', 'registry', 2, 1, 0, '{"required":"0","rule":""}', '2025-02-27 
17:20:50.233', '2025-02-27 17:20:50.233');
 UPDATE "public"."plugin_handle" SET ext_obj = '{"required":"0","rule":""}' 
WHERE plugin_id = '6' AND label = 'ip:port' AND data_type = 2;
 
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524917', '11', 
'corethreads', 'corethreads', 1, 1, 4, 
'{"required":"0","defaultValue":"","placeholder":"corethreads","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524918', '11', 
'threads', 'threads', 1, 1, 5, 
'{"required":"0","defaultValue":"","placeholder":"threads","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524919', '11', 
'queues', 'queues', 1, 1, 6, 
'{"required":"0","defaultValue":"","placeholder":"queues","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524920', '11', 
'threadpool', 'threadpool', 3, 1, 3, 
'{"required":"0","defaultValue":"","placeholder":"threadpool","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136289', '11', 
'protocol', 'protocol', 2, 1, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136290', '11', 
'register', 'register', 2, 1, 2, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
 
 INSERT INTO "public"."plugin_handle" VALUES ('1829402613204172834', '17', 
'registerProtocol', 'registerProtocol', 2, 1, 0, 
'{"required":"0","defaultValue":"","placeholder":"registerProtocol","rule":""}',
 '2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO "public"."plugin_handle" VALUES ('1829402613204172835', '17', 
'corethreads', 'corethreads', 1, 1, 2, 
'{"required":"0","defaultValue":"","placeholder":"corethreads","rule":""}', 
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
@@ -255,7 +261,6 @@ INSERT INTO "public"."plugin_handle" VALUES 
('1829402613204172837', '17', 'queue
 INSERT INTO "public"."plugin_handle" VALUES ('1829402613204172838', '17', 
'threadpool', 'threadpool', 3, 1, 5, 
'{"required":"0","defaultValue":"","placeholder":"threadpool","rule":""}', 
'2022-05-25 18:02:53', '2022-05-25 18:02:53');
 INSERT INTO "public"."plugin_handle" VALUES ('1878997557628272641', '17', 
'registerAddress', 'registerAddress', 2, 1, 1, 
'{"required":"0","defaultValue":"","placeholder":"registerAddress","rule":""}', 
'2023-01-10 10:08:01.158', '2023-01-10 10:08:01.158');
 
-
 INSERT INTO "public"."plugin" VALUES ('61', 'mcpServer', NULL, 'MCP', 180, 0, 
'2023-12-20 18:02:53', '2023-12-20 18:02:53', NULL);
 INSERT INTO "public"."namespace_plugin_rel" VALUES ('1801816010882832189', 
'649330b6-c2d7-4edc-be8e-8a54df9eb385', '61', NULL, 180, 0, '2022-05-25 
18:02:53.000', '2022-05-25 18:02:53.000');
 INSERT INTO "public"."plugin_handle" VALUES ('1942847622591684608', '61', 
'messageEndpoint', 'messageEndpoint', 2, 1, 0, 
'{"required":"0","defaultValue":"/message","rule":""}', '2025-07-09 
07:25:44.249', '2025-07-09 07:25:44.249');
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 e0762e9768..403d152956 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
@@ -555,6 +555,22 @@ VALUES ('1722804548510507249', '53', 'content', 'content', 
2, 2, 4, '{"required"
 
 delete from plugin_handle where plugin_id = '8';
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897210273825', '11', 'protocol', 'protocol', 2, 1, 1, null);
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897210273826', '11', 'register', 'register', 2, 1, 2, null);
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897214468164', '11', 'corethreads', 'corethreads', 1, 1, 4, 
'{"required":"0","defaultValue":"","placeholder":"corethreads","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897214468165', '11', 'threads', 'threads', 1, 1, 5, 
'{"required":"0","defaultValue":"","placeholder":"threads","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897214468166', '11', 'queues', 'queues', 1, 1, 6, 
'{"required":"0","defaultValue":"","placeholder":"queues","rule":""}');
+
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
+values ('1718229897214468167', '11', 'threadpool', 'threadpool', 3, 1, 3, 
'{"required":"0","defaultValue":"","placeholder":"threadpool","rule":""}');
 
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) 
*/ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, 
EXT_OBJ)
 values ('1818229897214468142', '17', 'registerProtocol', 'registerProtocol', 
2, 1, 0, 
'{"required":"0","defaultValue":"","placeholder":"registerProtocol","rule":""}');
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 beabbef9f9..e81cb74014 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
@@ -243,6 +243,15 @@ INSERT INTO "public"."permission" VALUES 
('1697146860569742758', '13463585604272
 INSERT INTO "public"."permission" VALUES ('1697146860569742759', 
'1346358560427216896', '1844026099075564867', '2023-08-31 07:18:37', 
'2023-08-31 07:18:37');
 INSERT INTO "public"."permission" VALUES ('1697146860569742760', 
'1346358560427216896', '1844026099075564868', '2023-08-31 07:18:37', 
'2023-08-31 07:18:37');
 
+DELETE FROM "public"."plugin_handle" WHERE plugin_id = '8';
+
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136289', '11', 
'protocol', 'protocol', 2, 1, 1, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902775136290', '11', 
'register', 'register', 2, 1, 2, NULL, '2022-05-25 18:08:01', '2022-05-25 
18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524917', '11', 
'corethreads', 'corethreads', 1, 1, 4, 
'{"required":"0","defaultValue":"","placeholder":"corethreads","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524918', '11', 
'threads', 'threads', 1, 1, 5, 
'{"required":"0","defaultValue":"","placeholder":"threads","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524919', '11', 
'queues', 'queues', 1, 1, 6, 
'{"required":"0","defaultValue":"","placeholder":"queues","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+INSERT INTO "public"."plugin_handle" VALUES ('1729403902783524920', '11', 
'threadpool', 'threadpool', 3, 1, 3, 
'{"required":"0","defaultValue":"","placeholder":"threadpool","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
+
 INSERT INTO "public"."plugin_handle" VALUES ('1829403902783524879', '17', 
'registerProtocol', 'registerProtocol', 2, 1, 0, 
'{"required":"0","defaultValue":"","placeholder":"registerProtocol","rule":""}',
 '2022-05-25 18:08:01', '2022-05-25 18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1878997557628272641', '17', 
'registerAddress', 'registerAddress', 2, 1, 1, 
'{"required":"0","defaultValue":"","placeholder":"registerAddress","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
 INSERT INTO "public"."plugin_handle" VALUES ('1829403902783524880', '17', 
'corethreads', 'corethreads', 1, 1, 2, 
'{"required":"0","defaultValue":"","placeholder":"corethreads","rule":""}', 
'2022-05-25 18:08:01', '2022-05-25 18:08:01');
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 96ceda58df..384aa24881 100644
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -650,6 +650,8 @@ INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES 
('1529402613199978533', '4', 'password', 'password', 2, 3, 4);
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES 
('1529402613199978534', '11', 'protocol', 'protocol', 2, 3, 1);
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES 
('1529402613199978535', '11', 'register', 'register', 2, 3, 2);
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES 
('1729402613199978534', '11', 'protocol', 'protocol', 2, 1, 1);
+INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES 
('1729402613199978535', '11', 'register', 'register', 2, 1, 2);
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES 
('1529402613199978536', '2', 'model', 'model', 2, 3, 1);
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`) VALUES 
('1529402613199978537', '6', 'register', 'register', 2, 3, 1);
 INSERT IGNORE INTO plugin_handle (`id`, 
`plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES 
('1529402613199978538', '4', 'algorithmName', 'algorithmName', 3, 2, 1, 
'{"required":"1","defaultValue":"slidingWindow","rule":""}');
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java 
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
index b9315ef5f0..5f5a964a32 100644
--- 
a/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/constant/Constants.java
@@ -588,6 +588,11 @@ public interface Constants {
      */
     String DUBBO_DEFAULT_APPLICATION_NAME = "shenyu_proxy";
 
+    /**
+     * sofa default application name.
+     */
+    String SOFA_DEFAULT_APPLICATION_NAME = "sofa";
+    
     /**
      * dubbo group.
      */
diff --git 
a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/selector/SofaUpstream.java
 
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/selector/SofaUpstream.java
new file mode 100644
index 0000000000..cf1f343dd2
--- /dev/null
+++ 
b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/selector/SofaUpstream.java
@@ -0,0 +1,347 @@
+/*
+ * 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.dto.convert.selector;
+
+import java.util.Objects;
+
+/**
+ * The type Sofa selector upstream.
+ */
+public final class SofaUpstream extends CommonUpstream {
+
+    /**
+     * registry url is required.
+     */
+    private String register;
+
+    /**
+     * sofa application name is required.
+     */
+    private String appName;
+
+    /**
+     * port.
+     */
+    private int port;
+
+    /**
+     * weight.
+     */
+    private int weight;
+
+    /**
+     * warmup.
+     */
+    private int warmup;
+
+    /**
+     * builder constructor.
+     *
+     * @param builder builder
+     */
+    private SofaUpstream(final Builder builder) {
+        boolean statusValue = builder.statusValue;
+        if (!builder.statusSet) {
+            statusValue = defaultStatus();
+        }
+        setUpstreamHost(builder.upstreamHost);
+        setProtocol(builder.protocol);
+        setUpstreamUrl(builder.upstreamUrl);
+        this.weight = builder.weight;
+        setStatus(statusValue);
+        setTimestamp(builder.timestamp);
+        this.warmup = builder.warmup;
+    }
+
+    /**
+     * class builder.
+     *
+     * @return Builder
+     */
+    public static Builder builder() {
+        return new Builder();
+    }
+
+    /**
+     * get registry.
+     *
+     * @return registry
+     */
+    public String getRegister() {
+        return register;
+    }
+
+    /**
+     * set registry.
+     *
+     * @param registry registry
+     */
+    public void setRegister(final String registry) {
+        this.register = register;
+    }
+
+    /**
+     * get appName.
+     *
+     * @return appName
+     */
+    public String getAppName() {
+        return appName;
+    }
+
+    /**
+     * set appName.
+     *
+     * @param appName appName
+     */
+    public void setAppName(final String appName) {
+        this.appName = appName;
+    }
+
+    /**
+     * get port.
+     *
+     * @return port
+     */
+    public int getPort() {
+        return port;
+    }
+
+    /**
+     * set port.
+     *
+     * @param port port
+     */
+    public void setPort(final int port) {
+        this.port = port;
+    }
+
+    /**
+     * Gets the value of weight.
+     *
+     * @return the value of weight
+     */
+    public int getWeight() {
+        return weight;
+    }
+
+    /**
+     * Sets the weight.
+     *
+     * @param weight weight
+     */
+    public void setWeight(final int weight) {
+        this.weight = weight;
+    }
+
+    /**
+     * Gets the value of warmup.
+     *
+     * @return the value of warmup
+     */
+    public int getWarmup() {
+        return warmup;
+    }
+
+    /**
+     * Sets the warmup.
+     *
+     * @param warmup warmup
+     */
+    public void setWarmup(final int warmup) {
+        this.warmup = warmup;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof SofaUpstream)) {
+            return false;
+        }
+        SofaUpstream that = (SofaUpstream) o;
+        return port == that.port
+                && Objects.equals(register, that.register)
+                && Objects.equals(appName, that.appName)
+                && Objects.equals(this.getProtocol(), that.getProtocol())
+                && Objects.equals(this.getUpstreamUrl(), that.getUpstreamUrl())
+                && Objects.equals(this.isGray(), that.isGray());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(register, appName, port, this.isGray());
+    }
+
+    @Override
+    public String toString() {
+        return "SofaUpstream{"
+                + "registry='" + register
+                + "', appName='" + appName
+                + "', protocol='" + this.getProtocol()
+                + "', port=" + port
+                + ", upstreamUrl='" + this.getUpstreamUrl()
+                + "', gray=" + this.isGray()
+                + ", weight=" + weight
+                + ", warmup=" + warmup
+                + ", status=" + isStatus()
+                + ", timestamp=" + getTimestamp()
+                + "'}";
+    }
+
+    /**
+     * class builder.
+     */
+    public static final class Builder {
+
+        /**
+         * upstreamHost.
+         */
+        private String upstreamHost;
+
+        /**
+         * protocol.
+         */
+        private String protocol;
+
+        /**
+         * upstreamUrl.
+         */
+        private String upstreamUrl;
+
+        /**
+         * weight.
+         */
+        private int weight;
+
+        /**
+         * status.
+         */
+        private boolean statusSet;
+
+        /**
+         * status.
+         */
+        private boolean statusValue;
+
+        /**
+         * timestamp.
+         */
+        private long timestamp;
+
+        /**
+         * warmup.
+         */
+        private int warmup;
+
+        /**
+         * no args constructor.
+         */
+        private Builder() {
+        }
+
+        /**
+         * build new Object.
+         *
+         * @return DivideUpstream
+         */
+        public SofaUpstream build() {
+            return new SofaUpstream(this);
+        }
+
+        /**
+         * build upstreamHost.
+         *
+         * @param upstreamHost upstreamHost
+         * @return this
+         */
+        public Builder upstreamHost(final String upstreamHost) {
+            this.upstreamHost = upstreamHost;
+            return this;
+        }
+
+        /**
+         * build protocol.
+         *
+         * @param protocol protocol
+         * @return this
+         */
+        public Builder protocol(final String protocol) {
+            this.protocol = protocol;
+            return this;
+        }
+
+        /**
+         * build upstreamUrl.
+         *
+         * @param upstreamUrl upstreamUrl
+         * @return this
+         */
+        public Builder upstreamUrl(final String upstreamUrl) {
+            this.upstreamUrl = upstreamUrl;
+            return this;
+        }
+
+        /**
+         * build weight.
+         *
+         * @param weight weight
+         * @return this
+         */
+        public Builder weight(final int weight) {
+            this.weight = weight;
+            return this;
+        }
+
+        /**
+         * build status.
+         *
+         * @param status status
+         * @return this
+         */
+        public Builder status(final boolean status) {
+            this.statusValue = status;
+            this.statusSet = true;
+            return this;
+        }
+
+        /**
+         * build timestamp.
+         *
+         * @param timestamp timestamp
+         * @return this
+         */
+        public Builder timestamp(final long timestamp) {
+            this.timestamp = timestamp;
+            return this;
+        }
+
+        /**
+         * build warmup.
+         *
+         * @param warmup warmup
+         * @return this
+         */
+        public Builder warmup(final int warmup) {
+            this.warmup = warmup;
+            return this;
+        }
+
+    }
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/SofaPlugin.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/SofaPlugin.java
index 558a30a844..11bd95edb1 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/SofaPlugin.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/SofaPlugin.java
@@ -86,7 +86,7 @@ public class SofaPlugin extends AbstractShenyuPlugin {
         }
         Map<String, Map<String, String>> rpcContext = 
exchange.getAttribute(Constants.GENERAL_CONTEXT);
         Optional.ofNullable(rpcContext).map(context -> 
context.get(PluginEnum.SOFA.getName())).ifPresent(context -> 
RpcInvokeContext.getContext().putAllRequestBaggage(context));
-        final Mono<Object> result = sofaProxyService.genericInvoker(param, 
metaData, exchange);
+        final Mono<Object> result = sofaProxyService.genericInvoker(param, 
metaData, selector, exchange);
         return result.then(chain.execute(exchange));
     }
 
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/cache/ApplicationConfigCache.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/cache/ApplicationConfigCache.java
index a9947f6272..1f9195668e 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/cache/ApplicationConfigCache.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/cache/ApplicationConfigCache.java
@@ -26,6 +26,7 @@ import com.alipay.sofa.rpc.context.AsyncRuntime;
 import com.google.common.cache.CacheBuilder;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
+import com.google.common.collect.Maps;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
 import org.apache.shenyu.common.concurrent.ShenyuThreadFactory;
@@ -33,8 +34,10 @@ import 
org.apache.shenyu.common.concurrent.ShenyuThreadPoolExecutor;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.MetaData;
 import org.apache.shenyu.common.dto.convert.plugin.SofaRegisterConfig;
+import org.apache.shenyu.common.dto.convert.selector.SofaUpstream;
 import org.apache.shenyu.common.enums.LoadBalanceEnum;
 import org.apache.shenyu.common.exception.ShenyuException;
+import org.apache.shenyu.common.utils.DigestUtils;
 import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.slf4j.Logger;
@@ -44,14 +47,20 @@ import org.springframework.lang.NonNull;
 import org.springframework.util.ReflectionUtils;
 
 import java.lang.reflect.Field;
+
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
+import java.util.StringJoiner;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 /**
  * The type Application config cache.
@@ -59,6 +68,8 @@ import java.util.concurrent.TimeUnit;
 public final class ApplicationConfigCache {
     
     private static final Logger LOG = 
LoggerFactory.getLogger(ApplicationConfigCache.class);
+
+    private static final Map<String, SofaUpstream> UPSTREAM_CACHE_MAP = 
Maps.newConcurrentMap();
     
     private final ThreadFactory factory = 
ShenyuThreadFactory.create("shenyu-sofa", true);
     
@@ -118,11 +129,12 @@ public final class ApplicationConfigCache {
         }
         if (Objects.isNull(registryConfig)) {
             registryConfig = new RegistryConfig();
-            registryConfig.setProtocol(sofaRegisterConfig.getProtocol());
             registryConfig.setId(shenyuProxy);
             registryConfig.setRegister(false);
-            registryConfig.setAddress(sofaRegisterConfig.getRegister());
+
         }
+        registryConfig.setProtocol(sofaRegisterConfig.getProtocol());
+        registryConfig.setAddress(sofaRegisterConfig.getRegister());
         if (StringUtils.isNotBlank(sofaRegisterConfig.getThreadpool())) {
             initThreadPool(sofaRegisterConfig);
             
Optional.ofNullable(threadPool).ifPresent(this::setAsyncRuntimeThreadPool);
@@ -186,7 +198,52 @@ public final class ApplicationConfigCache {
         return build(metaData);
         
     }
-    
+
+    /**
+     * Init ref reference config use sofaUpstream.
+     *
+     * @param selectorId    the selectorId
+     * @param metaData      the meta data
+     * @param sofaUpstream  the sofaUpstream
+     * @return the reference config
+     */
+    public ConsumerConfig<GenericService> initRef(final String selectorId, 
final MetaData metaData, final SofaUpstream sofaUpstream) {
+        try {
+            String cacheKey = generateUpstreamCacheKey(selectorId, 
metaData.getPath(), sofaUpstream);
+            ConsumerConfig<GenericService> referenceConfig = 
cache.get(cacheKey);
+            if (StringUtils.isNoneBlank(referenceConfig.getInterfaceId())) {
+                return referenceConfig;
+            }
+        } catch (ExecutionException e) {
+            LOG.error("init sofa ref ex:{}", e.getMessage());
+        }
+        return build(metaData, selectorId, sofaUpstream);
+
+    }
+
+    /**
+     * generate sofa upstream reference cache key.
+     *
+     * @param selectorId    selectorId
+     * @param metaDataPath    metaDataPath
+     * @param sofaUpstream  sofaUpstream
+     * @return the reference config cache key
+     */
+    public String generateUpstreamCacheKey(final String selectorId, final 
String metaDataPath, final SofaUpstream sofaUpstream) {
+        StringJoiner stringJoiner = new 
StringJoiner(Constants.SEPARATOR_UNDERLINE);
+        stringJoiner.add(selectorId);
+        stringJoiner.add(metaDataPath);
+        if (StringUtils.isNotBlank(sofaUpstream.getProtocol())) {
+            stringJoiner.add(sofaUpstream.getProtocol());
+        }
+        // use registry hash to short reference cache key
+        String registryHash = DigestUtils.md5Hex(sofaUpstream.getRegister());
+        stringJoiner.add(registryHash);
+        return stringJoiner.toString();
+    }
+
+
+
     /**
      * Build reference config.
      *
@@ -197,6 +254,54 @@ public final class ApplicationConfigCache {
         if (Objects.isNull(applicationConfig) || 
Objects.isNull(registryConfig)) {
             return new ConsumerConfig<>();
         }
+        ConsumerConfig<GenericService> reference = buildReference(metaData);
+        try {
+            Object obj = reference.refer();
+            if (Objects.nonNull(obj)) {
+                LOG.info("init sofa reference success there meteData is :{}", 
metaData);
+                cache.put(metaData.getPath(), reference);
+            }
+        } catch (Exception e) {
+            LOG.error("init sofa reference exception", e);
+        }
+        return reference;
+    }
+
+    /**
+     * build with dynamic namespace and selectorData's SofaUpstream、ruleData's 
custom param.
+     *
+     * @param metaData      metaData
+     * @param selectorId    selectorId
+     * @param sofaUpstream  sofaUpstream
+     * @return the reference config
+     */
+    @SuppressWarnings("deprecation")
+    public ConsumerConfig<GenericService> build(final MetaData metaData, final 
String selectorId, final SofaUpstream sofaUpstream) {
+        if (Objects.isNull(sofaUpstream)) {
+            return this.build(metaData);
+        }
+
+        ConsumerConfig<GenericService> reference = buildReference(metaData, 
sofaUpstream);
+        try {
+            Object obj = reference.refer();
+            if (Objects.nonNull(obj)) {
+                LOG.info("buildN init apache sofa reference success there 
meteData is :{}", metaData);
+                String cacheKey = this.generateUpstreamCacheKey(selectorId, 
metaData.getPath(), sofaUpstream);
+                cache.put(cacheKey, reference);
+            }
+        } catch (Exception e) {
+            LOG.error("buildN init sofa reference exception", e);
+        }
+        return reference;
+    }
+
+    /**
+     * buildReference param.
+     *
+     * @param metaData metaData
+     * @return the reference config
+     */
+    private ConsumerConfig<GenericService> buildReference(final MetaData 
metaData) {
         ConsumerConfig<GenericService> reference = new ConsumerConfig<>();
         reference.setGeneric(true);
         reference.setApplication(applicationConfig);
@@ -215,18 +320,52 @@ public final class ApplicationConfigCache {
             
Optional.ofNullable(sofaParamExtInfo.getTimeout()).ifPresent(reference::setTimeout);
             
Optional.ofNullable(sofaParamExtInfo.getRetries()).ifPresent(reference::setRetries);
         }
-        try {
-            Object obj = reference.refer();
-            if (Objects.nonNull(obj)) {
-                LOG.info("init sofa reference success there meteData is :{}", 
metaData);
-                cache.put(metaData.getPath(), reference);
+        return reference;
+    }
+
+    /**
+     * buildReference param with sofaUpstream.
+     *
+     * @param metaData      metaData
+     * @param sofaUpstream  sofaUpstream
+     * @return the reference config
+     */
+    private ConsumerConfig<GenericService> buildReference(final MetaData 
metaData, final SofaUpstream sofaUpstream) {
+        if (Objects.isNull(applicationConfig) || 
Objects.isNull(registryConfig)) {
+            return new ConsumerConfig<>();
+        }
+        ConsumerConfig<GenericService> reference = new ConsumerConfig<>();
+        reference.setGeneric(true);
+        reference.setApplication(applicationConfig);
+
+        if (Objects.nonNull(sofaUpstream)) {
+            RegistryConfig registryConfigTemp = new RegistryConfig();
+            registryConfigTemp.setProtocol(sofaUpstream.getProtocol());
+            registryConfigTemp.setId(Constants.SOFA_DEFAULT_APPLICATION_NAME);
+            registryConfigTemp.setRegister(false);
+            registryConfigTemp.setAddress(sofaUpstream.getRegister());
+            reference.setRegistry(registryConfigTemp);
+        } else {
+            reference.setRegistry(registryConfig);
+        }
+
+        reference.setInterfaceId(metaData.getServiceName());
+        reference.setProtocol(RpcConstants.PROTOCOL_TYPE_BOLT);
+        reference.setInvokeType(RpcConstants.INVOKER_TYPE_CALLBACK);
+        reference.setRepeatedReferLimit(-1);
+        String rpcExt = metaData.getRpcExt();
+        SofaParamExtInfo sofaParamExtInfo = 
GsonUtils.getInstance().fromJson(rpcExt, SofaParamExtInfo.class);
+        if (Objects.nonNull(sofaParamExtInfo)) {
+            if (StringUtils.isNoneBlank(sofaParamExtInfo.getLoadbalance())) {
+                final String loadBalance = sofaParamExtInfo.getLoadbalance();
+                reference.setLoadBalancer(buildLoadBalanceName(loadBalance));
             }
-        } catch (Exception e) {
-            LOG.error("init sofa reference exception", e);
+            
Optional.ofNullable(sofaParamExtInfo.getTimeout()).ifPresent(reference::setTimeout);
+            
Optional.ofNullable(sofaParamExtInfo.getRetries()).ifPresent(reference::setRetries);
         }
         return reference;
     }
-    
+
     private String buildLoadBalanceName(final String loadBalance) {
         if (LoadBalanceEnum.HASH.getName().equals(loadBalance) || 
StringUtils.equalsIgnoreCase("consistenthash", loadBalance)) {
             return "consistentHash";
@@ -250,6 +389,27 @@ public final class ApplicationConfigCache {
             throw new ShenyuException(e.getCause());
         }
     }
+
+    /**
+     * Get Upstream.
+     *
+     * @param path path
+     * @return the upstream
+     */
+    public SofaUpstream getUpstream(final String path) {
+        return UPSTREAM_CACHE_MAP.get(path);
+    }
+
+    /**
+     * Put Upstream.
+     *
+     * @param path path
+     * @param sofaUpstream sofaUpstream
+     * @return the upstreamList
+     */
+    public SofaUpstream putUpstream(final String path, final SofaUpstream 
sofaUpstream) {
+        return UPSTREAM_CACHE_MAP.put(path, sofaUpstream);
+    }
     
     /**
      * Invalidate.
@@ -265,6 +425,45 @@ public final class ApplicationConfigCache {
      */
     public void invalidateAll() {
         cache.invalidateAll();
+        UPSTREAM_CACHE_MAP.clear();
+    }
+
+    /**
+     * Invalidate when sofa metadata update.
+     *
+     * @param metadataPath the metadataPath
+     */
+    public void invalidateWithMetadataPath(final String metadataPath) {
+        ConcurrentMap<String, ConsumerConfig<GenericService>> map = 
cache.asMap();
+        if (map.isEmpty()) {
+            return;
+        }
+        Set<String> allKeys = map.keySet();
+        Set<String> needInvalidateKeys = allKeys.stream().filter(key -> 
key.contains(metadataPath)).collect(Collectors.toSet());
+        if (needInvalidateKeys.isEmpty()) {
+            return;
+        }
+        needInvalidateKeys.forEach(cache::invalidate);
+        needInvalidateKeys.forEach(UPSTREAM_CACHE_MAP::remove);
+    }
+
+    /**
+     * Invalidate when sofa selector update.
+     *
+     * @param selectorId the selectorId
+     */
+    public void invalidateWithSelectorId(final String selectorId) {
+        ConcurrentMap<String, ConsumerConfig<GenericService>> map = 
cache.asMap();
+        if (map.isEmpty()) {
+            return;
+        }
+        Set<String> allKeys = map.keySet();
+        Set<String> needInvalidateKeys = allKeys.stream().filter(key -> 
key.contains(selectorId)).collect(Collectors.toSet());
+        if (needInvalidateKeys.isEmpty()) {
+            return;
+        }
+        needInvalidateKeys.forEach(cache::invalidate);
+        needInvalidateKeys.forEach(UPSTREAM_CACHE_MAP::remove);
     }
     
     /**
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaMetaDataHandler.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaMetaDataHandler.java
index 200c8aad03..a318780d19 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaMetaDataHandler.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaMetaDataHandler.java
@@ -41,6 +41,8 @@ public class SofaMetaDataHandler implements MetaDataHandler {
             ApplicationConfigCache.getInstance().initRef(metaData);
         } else {
             if (!exist.getServiceName().equals(metaData.getServiceName()) || 
!exist.getRpcExt().equals(metaData.getRpcExt())) {
+                // remove old upstream reference
+                
ApplicationConfigCache.getInstance().invalidateWithMetadataPath(metaData.getPath());
                 // update
                 ApplicationConfigCache.getInstance().build(metaData);
             }
@@ -50,7 +52,7 @@ public class SofaMetaDataHandler implements MetaDataHandler {
     
     @Override
     public void remove(final MetaData metaData) {
-        ApplicationConfigCache.getInstance().invalidate(metaData.getPath());
+        
ApplicationConfigCache.getInstance().invalidateWithMetadataPath(metaData.getPath());
         META_DATA.remove(metaData.getPath());
     }
     
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaPluginDataHandler.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaPluginDataHandler.java
index 23e69dac4e..9268046162 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaPluginDataHandler.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/handler/SofaPluginDataHandler.java
@@ -17,8 +17,10 @@
 
 package org.apache.shenyu.plugin.sofa.handler;
 
+import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.dto.convert.plugin.SofaRegisterConfig;
 import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.dto.convert.selector.SofaUpstream;
 import org.apache.shenyu.common.enums.PluginEnum;
 import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
@@ -49,6 +51,25 @@ public class SofaPluginDataHandler implements 
PluginDataHandler {
         }
     }
 
+    @Override
+    public void handlerSelector(final SelectorData selectorData) {
+        SofaUpstream nCacheUpstreams = 
GsonUtils.getInstance().fromJson(selectorData.getHandle(), SofaUpstream.class);
+        SofaUpstream oCacheUpstream = 
ApplicationConfigCache.getInstance().getUpstream(selectorData.getId());
+        if (!Objects.equals(nCacheUpstreams, oCacheUpstream)) {
+            
ApplicationConfigCache.getInstance().invalidateWithSelectorId(selectorData.getId());
+        }
+    }
+
+    @Override
+    public void removePlugin(final PluginData pluginData) {
+        ApplicationConfigCache.getInstance().invalidateAll();
+    }
+    
+    @Override
+    public void removeSelector(final SelectorData selectorData) {
+        
ApplicationConfigCache.getInstance().invalidateWithSelectorId(selectorData.getId());
+    }
+
     @Override
     public String pluginNamed() {
         return PluginEnum.SOFA.getName();
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyService.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyService.java
index 087e410f48..91895cc533 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyService.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/main/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyService.java
@@ -29,8 +29,11 @@ import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.dto.convert.selector.SofaUpstream;
 import org.apache.shenyu.common.enums.ResultEnum;
 import org.apache.shenyu.common.exception.ShenyuException;
+import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.common.utils.ParamCheckUtils;
 import org.apache.shenyu.plugin.sofa.cache.ApplicationConfigCache;
 import org.apache.shenyu.plugin.sofa.param.SofaParamResolveService;
@@ -63,19 +66,15 @@ public class SofaProxyService {
     /**
      * Generic invoker object.
      *
-     * @param body     the body
-     * @param metaData the meta data
-     * @param exchange the exchange
+     * @param body          the body
+     * @param metaData      the meta data
+     * @param selectorData  the selector data
+     * @param exchange      the webExchange
      * @return the object
      * @throws ShenyuException the shenyu exception
      */
-    public Mono<Object> genericInvoker(final String body, final MetaData 
metaData, final ServerWebExchange exchange) throws ShenyuException {
-        ConsumerConfig<GenericService> reference = 
ApplicationConfigCache.getInstance().get(metaData.getPath());
-        if (Objects.isNull(reference) || 
StringUtils.isEmpty(reference.getInterfaceId())) {
-            
ApplicationConfigCache.getInstance().invalidate(metaData.getPath());
-            reference = ApplicationConfigCache.getInstance().initRef(metaData);
-        }
-        
+    public Mono<Object> genericInvoker(final String body, final MetaData 
metaData, final SelectorData selectorData, final ServerWebExchange exchange) 
throws ShenyuException {
+        ConsumerConfig<GenericService> reference = 
this.getConsumerConfig(selectorData, metaData, exchange);
         Pair<String[], Object[]> pair;
         if (StringUtils.isBlank(metaData.getParameterTypes()) || 
ParamCheckUtils.bodyIsEmpty(body)) {
             pair = new ImmutablePair<>(new String[]{}, new Object[]{});
@@ -113,4 +112,27 @@ public class SofaProxyService {
             return result;
         })).onErrorMap(ShenyuException::new);
     }
+
+    private ConsumerConfig<GenericService> getConsumerConfig(final 
SelectorData selectorData, final MetaData metaData, final ServerWebExchange 
exchange) {
+        String referenceKey = metaData.getPath();
+        SofaUpstream sofaUpstream = 
GsonUtils.getInstance().fromJson(selectorData.getHandle(), SofaUpstream.class);
+        // if sofaUpstreams is empty, use default plugin config
+        if (Objects.isNull(sofaUpstream)) {
+            ConsumerConfig<GenericService> reference = 
ApplicationConfigCache.getInstance().get(referenceKey);
+            if (StringUtils.isEmpty(reference.getInterfaceId())) {
+                ApplicationConfigCache.getInstance().invalidate(referenceKey);
+                reference = 
ApplicationConfigCache.getInstance().initRef(metaData);
+            }
+            return reference;
+        }
+        referenceKey = 
ApplicationConfigCache.getInstance().generateUpstreamCacheKey(selectorData.getId(),
 metaData.getPath(), sofaUpstream);
+        ConsumerConfig<GenericService> reference = 
ApplicationConfigCache.getInstance().get(referenceKey);
+        if (StringUtils.isEmpty(reference.getInterfaceId())) {
+            ApplicationConfigCache.getInstance().invalidate(referenceKey);
+            reference = 
ApplicationConfigCache.getInstance().initRef(selectorData.getId(), metaData, 
sofaUpstream);
+            ApplicationConfigCache.getInstance().putUpstream(referenceKey, 
sofaUpstream);
+        }
+        return reference;
+    }
+
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/SofaPluginTest.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/SofaPluginTest.java
index fff0ba6650..3f7b2d9519 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/SofaPluginTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/SofaPluginTest.java
@@ -45,6 +45,8 @@ import reactor.test.StepVerifier;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -74,7 +76,7 @@ public final class SofaPluginTest {
         metaData.setMethodName("findAll");
         metaData.setRpcType(RpcTypeEnum.SOFA.getName());
         SofaProxyService sofaProxyService = mock(SofaProxyService.class);
-        when(sofaProxyService.genericInvoker(null, metaData, 
exchange)).thenReturn(Mono.empty());
+        when(sofaProxyService.genericInvoker(eq(null), eq(metaData), any(), 
eq(exchange))).thenReturn(Mono.empty());
         sofaPlugin = new SofaPlugin(sofaProxyService);
     }
 
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/cache/ApplicationConfigCacheTest.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/cache/ApplicationConfigCacheTest.java
new file mode 100644
index 0000000000..3a009deaff
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/cache/ApplicationConfigCacheTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.plugin.sofa.cache;
+
+import com.alipay.sofa.rpc.config.ConsumerConfig;
+import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.dto.convert.plugin.SofaRegisterConfig;
+import org.apache.shenyu.common.dto.convert.selector.SofaUpstream;
+import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+/**
+ * ApplicationConfigCacheTest.
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+public class ApplicationConfigCacheTest {
+
+    private ApplicationConfigCache cache;
+
+    private MetaData metaData;
+
+    @Mock
+    private SelectorData selectorData;
+
+    @BeforeEach
+    void setUp() {
+        metaData = new MetaData();
+        metaData.setId("1332017966661636096");
+        metaData.setAppName("sofa");
+        metaData.setPath("/sofa/findAll");
+        
metaData.setServiceName("org.apache.shenyu.test.dubbo.api.service.DubboTestService");
+        metaData.setMethodName("findAll");
+        metaData.setRpcType(RpcTypeEnum.SOFA.getName());
+        when(selectorData.getId()).thenReturn("153153464562434");
+        cache = ApplicationConfigCache.getInstance();
+        cache.invalidateAll();
+    }
+
+    @Test
+    void testInitRefAndGet() {
+        SofaRegisterConfig config = mock(SofaRegisterConfig.class);
+        when(config.getProtocol()).thenReturn("zookeeper");
+        when(config.getRegister()).thenReturn("127.0.0.1:2181");
+        cache.init(config);
+
+        ConsumerConfig<com.alipay.sofa.rpc.api.GenericService> refConfig = 
cache.initRef(metaData);
+        assertNotNull(refConfig);
+        
assertEquals("org.apache.shenyu.test.dubbo.api.service.DubboTestService", 
refConfig.getInterfaceId());
+
+    }
+
+    @Test
+    void testInitRef2AndGet() {
+
+        SofaRegisterConfig config = mock(SofaRegisterConfig.class);
+        when(config.getProtocol()).thenReturn("zookeeper");
+        when(config.getRegister()).thenReturn("127.0.0.1:2181");
+        cache.init(config);
+
+        SofaUpstream sofaUpstream = mock(SofaUpstream.class);
+        when(sofaUpstream.getProtocol()).thenReturn("zookeeper");
+        when(sofaUpstream.getRegister()).thenReturn("127.0.0.1:2182");
+        ConsumerConfig<com.alipay.sofa.rpc.api.GenericService> refConfig = 
cache.initRef(selectorData.getId(), metaData, sofaUpstream);
+        assertNotNull(refConfig);
+        
assertEquals("org.apache.shenyu.test.dubbo.api.service.DubboTestService", 
refConfig.getInterfaceId());
+        assertEquals("127.0.0.1:2182", 
refConfig.getRegistry().get(0).getAddress());
+    }
+
+}
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyServiceTest.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyServiceTest.java
index daa165261d..218c7106c5 100644
--- 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyServiceTest.java
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-sofa/src/test/java/org/apache/shenyu/plugin/sofa/proxy/SofaProxyServiceTest.java
@@ -27,8 +27,11 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.shenyu.common.concurrent.ShenyuThreadPoolExecutor;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.MetaData;
+import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.dto.convert.plugin.SofaRegisterConfig;
+import org.apache.shenyu.common.dto.convert.selector.SofaUpstream;
 import org.apache.shenyu.common.enums.RpcTypeEnum;
+import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.sofa.cache.ApplicationConfigCache;
 import org.apache.shenyu.plugin.sofa.param.SofaParamResolveService;
@@ -57,19 +60,19 @@ import static org.mockito.Mockito.when;
  */
 @ExtendWith(MockitoExtension.class)
 public final class SofaProxyServiceTest {
-    
+
     private static final String PATH = "/sofa/findAll";
-    
+
     private static final String METHOD_NAME = "findAll";
-    
+
     private static final String[] LEFT = new String[]{};
-    
+
     private static final Object[] RIGHT = new Object[]{};
-    
+
     private MetaData metaData;
-    
+
     private ServerWebExchange exchange;
-    
+
     @BeforeEach
     public void setup() {
         exchange = 
MockServerWebExchange.from(MockServerHttpRequest.get("localhost").build());
@@ -82,12 +85,12 @@ public final class SofaProxyServiceTest {
         metaData.setRpcType(RpcTypeEnum.SOFA.getName());
         metaData.setRpcExt("{\"loadbalance\": \"loadbalance\"}");
     }
-    
+
     @AfterEach
     public void after() {
         ApplicationConfigCache.getInstance().invalidateAll();
     }
-    
+
     @Test
     @SuppressWarnings("all")
     public void testGenericInvoker() throws IllegalAccessException {
@@ -103,13 +106,49 @@ public final class SofaProxyServiceTest {
         assertTrue(cache instanceof LoadingCache);
         ((LoadingCache) cache).put(PATH, consumerConfig);
         SofaProxyService sofaProxyService = new SofaProxyService(new 
SofaParamResolveServiceImpl());
-        sofaProxyService.genericInvoker("", metaData, exchange);
+        sofaProxyService.genericInvoker("", metaData, new SelectorData(), 
exchange);
         
RpcInvokeContext.getContext().getResponseCallback().onAppResponse("success", 
null, null);
         final SofaRegisterConfig sofaRegisterConfig = new SofaRegisterConfig();
         sofaRegisterConfig.setThreadpool(Constants.SHARED);
         applicationConfigCache.init(sofaRegisterConfig);
     }
 
+    @Test
+    @SuppressWarnings("all")
+    public void testGenericInvoker2() throws IllegalAccessException {
+        ConsumerConfig consumerConfig = mock(ConsumerConfig.class);
+        GenericService genericService = mock(GenericService.class);
+        when(consumerConfig.refer()).thenReturn(genericService);
+        when(consumerConfig.getInterfaceId()).thenReturn(PATH);
+        when(genericService.$genericInvoke(METHOD_NAME, LEFT, 
RIGHT)).thenReturn(null);
+        ApplicationConfigCache applicationConfigCache = 
ApplicationConfigCache.getInstance();
+        SelectorData selectorData = 
SelectorData.builder().id("153153464562434")
+                .handle("{\n" + "  \"register\": 
\"zookeeper://127.0.0.1:2181\",\n"
+                        + "  \"appName\": \"sofa-demo-service\",\n"
+                        + "  \"port\": 12200,\n"
+                        + "  \"weight\": 50,\n"
+                        + "  \"warmup\": 60,\n"
+                        + "  \"upstreamHost\": \"127.0.0.1\",\n"
+                        + "  \"protocol\": \"zookeeper\",\n"
+                        + "  \"upstreamUrl\": \"127.0.0.1:12200\",\n"
+                        + "  \"gray\": false,\n"
+                        + "  \"status\": true,\n"
+                        + "  \"timestamp\": 1718001234567\n"
+                        + "}").build();
+        SofaUpstream sofaUpstream = 
GsonUtils.getInstance().fromJson(selectorData.getHandle(), SofaUpstream.class);
+        final Field cacheField = 
FieldUtils.getDeclaredField(ApplicationConfigCache.class, "cache", true);
+        assertNotNull(cacheField);
+        final Object cache = cacheField.get(applicationConfigCache);
+        assertTrue(cache instanceof LoadingCache);
+        String key = 
applicationConfigCache.generateUpstreamCacheKey("153153464562434", PATH, 
sofaUpstream);
+        ((LoadingCache) cache).put(key, consumerConfig);
+        SofaProxyService sofaProxyService = new SofaProxyService(new 
SofaParamResolveServiceImpl());
+        final SofaRegisterConfig sofaRegisterConfig = new SofaRegisterConfig();
+        applicationConfigCache.init(sofaRegisterConfig);
+        sofaProxyService.genericInvoker("", metaData, selectorData, exchange);
+        
RpcInvokeContext.getContext().getResponseCallback().onAppResponse("success", 
null, null);
+    }
+
     @Test
     public void applicationConfigCacheTest() throws NoSuchFieldException, 
IllegalAccessException {
         ConfigurableApplicationContext context = 
mock(ConfigurableApplicationContext.class);
@@ -146,9 +185,9 @@ public final class SofaProxyServiceTest {
         applicationConfigCache.init(sofaRegisterConfig);
         applicationConfigCache.build(metaData);
     }
-    
+
     static class SofaParamResolveServiceImpl implements 
SofaParamResolveService {
-        
+
         @Override
         @NonNull
         public Pair<String[], Object[]> buildParameter(final String body, 
final String parameterTypes) {

Reply via email to