增加nacos - rule

This commit is contained in:
mll 2022-09-15 20:26:57 +08:00
parent 088b415179
commit baaddb013e
17 changed files with 493 additions and 6 deletions

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>liteflow-rule-plugin</artifactId>
<groupId>com.yomahub</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liteflow-rule-nacos</artifactId>
<dependencies>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-core</artifactId>
<version>${revision}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,66 @@
package com.yomahub.liteflow.parser.nacos;
import cn.hutool.core.util.StrUtil;
import com.yomahub.liteflow.parser.el.ClassXmlFlowELParser;
import com.yomahub.liteflow.parser.nacos.exception.NacosException;
import com.yomahub.liteflow.parser.nacos.util.NacosParserHelper;
import com.yomahub.liteflow.parser.nacos.vo.NacosParserVO;
import com.yomahub.liteflow.property.LiteflowConfig;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.util.JsonUtil;
import java.util.function.Consumer;
/**
* Nacos 解析器实现只支持EL形式的XML不支持其他的形式
* @author mll
* @since 2.9.0
*/
public class NacosXmlELParser extends ClassXmlFlowELParser {
private final NacosParserHelper helper;
public NacosXmlELParser() {
Consumer<String> parseConsumer = t -> {
try {
parse(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
LiteflowConfig liteflowConfig = LiteflowConfigGetter.get();
if (StrUtil.isBlank(liteflowConfig.getRuleSourceExtData())){
throw new NacosException("rule-source-ext-data for nacos is empty");
}
try{
NacosParserVO nacosParserVO = JsonUtil.parseObject(liteflowConfig.getRuleSourceExtData(), NacosParserVO.class);
assert nacosParserVO != null;
if (StrUtil.isBlank(nacosParserVO.getServerAddr())){
nacosParserVO.setServerAddr("127.0.0.1:8848");
}
if (StrUtil.isBlank(nacosParserVO.getDataId())){
nacosParserVO.setDataId("LiteFLow");
}
if (StrUtil.isBlank(nacosParserVO.getGroup())){
nacosParserVO.setGroup("LiteFLowConfig");
}
helper = new NacosParserHelper(nacosParserVO, parseConsumer);
}catch (Exception e){
throw new NacosException(e.getMessage());
}
}
@Override
public String parseCustom() {
try{
String content = helper.getContent();
helper.checkContent(content);
helper.listener();
return content;
}catch (Exception e){
throw new NacosException(e.getMessage());
}
}
}

View File

@ -0,0 +1,23 @@
package com.yomahub.liteflow.parser.nacos.exception;
public class NacosException extends RuntimeException {
private static final long serialVersionUID = 1L;
/** 异常信息 */
private String message;
public NacosException(String message) {
this.message = message;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}

View File

@ -0,0 +1,94 @@
package com.yomahub.liteflow.parser.nacos.util;
import cn.hutool.core.util.StrUtil;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.yomahub.liteflow.exception.ParseException;
import com.yomahub.liteflow.parser.nacos.exception.NacosException;
import com.yomahub.liteflow.parser.nacos.vo.NacosParserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.MessageFormat;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* Nacos client for http api
* <a href="https://nacos.io/zh-cn/docs/open-api.html">OpenAPI</a>
* @author mll
* @since 2.9.0
*/
public class NacosParserHelper {
private static final Logger LOG = LoggerFactory.getLogger(NacosParserHelper.class);
private final NacosParserVO nacosParserVO;
private final Consumer<String> parseConsumer;
private static final ConcurrentHashMap<String,String> CONFIG_MAP = new ConcurrentHashMap<>(1);
private final ConfigService configService;
static {
CONFIG_MAP.put("Content","");
}
public NacosParserHelper(NacosParserVO nacosParserVO, Consumer<String> parseConsumer) {
this.nacosParserVO = nacosParserVO;
this.parseConsumer = parseConsumer;
try{
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, nacosParserVO.getServerAddr());
this.configService = NacosFactory.createConfigService(properties);
CONFIG_MAP.put("Content",configService.getConfig(nacosParserVO.getDataId(), nacosParserVO.getGroup(), 3000L));
}catch (Exception e){
throw new NacosException(e.getMessage());
}
}
public String getContent(){
try{
return CONFIG_MAP.get("Content");
}catch (Exception e){
throw new NacosException(e.getMessage());
}
}
/**
* 检查 content 是否合法
*/
public void checkContent(String content) {
if (StrUtil.isBlank(content)) {
String error = MessageFormat.format("the node[{0}] value is empty", nacosParserVO.toString());
throw new ParseException(error);
}
}
/**
* 监听 nacos 数据变化
*/
public void listener() {
try {
this.configService.addListener(nacosParserVO.getDataId(), nacosParserVO.getGroup(), new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
LOG.info("stating load flow config.... {} " , configInfo);
CONFIG_MAP.put("Content",configInfo);
parseConsumer.accept(configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
}catch (Exception ex){
LOG.error("listener Exception {} " , ex.getMessage());
throw new NacosException(ex.getMessage());
}
}
}

View File

@ -0,0 +1,69 @@
package com.yomahub.liteflow.parser.nacos.vo;
/**
* 用于解析 RuleSourceExtData 的vo类用于nacos模式中
* @author mll
* @since 2.9.0
*/
public class NacosParserVO {
private String serverAddr;
private String namespace;
private String dataId;
private String group;
private String username;
private String password;
public String getServerAddr() {
return serverAddr;
}
public void setServerAddr(String serverAddr) {
this.serverAddr = serverAddr;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public String getDataId() {
return dataId;
}
public void setDataId(String dataId) {
this.dataId = dataId;
}
public String getGroup() {
return group;
}
public void setGroup(String group) {
this.group = group;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "NacosParserVO{" + "serverAddr='" + serverAddr + '\'' + ", namespace='" + namespace + '\'' + ", dataId='" + dataId + '\'' + ", group='" + group + '\''
+ ", username='" + username + '\'' + ", password='" + password + '\'' + '}';
}
}

View File

@ -0,0 +1,17 @@
package com.yomahub.liteflow.parser.spi.nacos;
import com.yomahub.liteflow.parser.nacos.NacosXmlELParser;
import com.yomahub.liteflow.parser.spi.ParserClassNameSpi;
/**
* Nacos 解析器SPI实现
* @author mll
* @since 2.9.0
*/
public class NacosParserClassNameSpi implements ParserClassNameSpi {
@Override
public String getSpiClassName() {
return NacosXmlELParser.class.getName();
}
}

View File

@ -0,0 +1 @@
com.yomahub.liteflow.parser.spi.nacos.NacosParserClassNameSpi

View File

@ -12,6 +12,7 @@
<packaging>pom</packaging>
<modules>
<module>liteflow-rule-zk</module>
<module>liteflow-rule-nacos</module>
</modules>
<artifactId>liteflow-rule-plugin</artifactId>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>liteflow-testcase-el</artifactId>
<groupId>com.yomahub</groupId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>liteflow-testcase-el-nacos-springboot</artifactId>
<dependencies>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-spring-boot-starter</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.yomahub</groupId>
<artifactId>liteflow-rule-nacos</artifactId>
<version>${revision}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${springboot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,20 @@
package com.yomahub.liteflow.test;
import com.yomahub.liteflow.flow.FlowBus;
import com.yomahub.liteflow.property.LiteflowConfigGetter;
import com.yomahub.liteflow.spi.holder.SpiFactoryCleaner;
import com.yomahub.liteflow.spring.ComponentScanner;
import com.yomahub.liteflow.thread.ExecutorHelper;
import org.junit.AfterClass;
public class BaseTest {
@AfterClass
public static void cleanScanCache(){
ComponentScanner.cleanCache();
FlowBus.cleanCache();
ExecutorHelper.loadInstance().clearExecutorServiceMap();
SpiFactoryCleaner.clean();
LiteflowConfigGetter.clean();
}
}

View File

@ -0,0 +1,44 @@
package com.yomahub.liteflow.test.nacos;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.flow.LiteflowResponse;
import com.yomahub.liteflow.test.BaseTest;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
/**
* springboot环境下的nacos配置源功能测试
* nacos存储数据的格式为xml文件
* @author mll
* @since 2.9.0
*/
@RunWith(SpringRunner.class)
@TestPropertySource(value = "classpath:/nacos/application-xml.properties")
@SpringBootTest(classes = NacosWithXmlELSpringbootTest.class)
@EnableAutoConfiguration
@ComponentScan({"com.yomahub.liteflow.test.nacos.cmp"})
public class NacosWithXmlELSpringbootTest extends BaseTest {
@Resource
private FlowExecutor flowExecutor;
@Test
public void testNacosWithXml() throws Exception {
LiteflowResponse response = flowExecutor.execute2Resp("chain1", "arg");
Assert.assertTrue(response.isSuccess());
Assert.assertEquals("a==>b==>c", response.getExecuteStepStr());
for (int i = 0 ; i < 10; i ++){
Thread.sleep(10000L);
response = flowExecutor.execute2Resp("chain1", "arg");
System.out.println(" i " + response.getExecuteStepStr());
}
}
}

View File

@ -0,0 +1,20 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.nacos.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("a")
public class ACmp extends NodeComponent {
@Override
public void process() {
System.out.println("ACmp executed!");
}
}

View File

@ -0,0 +1,21 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.nacos.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("b")
public class BCmp extends NodeComponent {
@Override
public void process() {
System.out.println("BCmp executed!");
}
}

View File

@ -0,0 +1,21 @@
/**
* <p>Title: liteflow</p>
* <p>Description: 轻量级的组件式流程框架</p>
* @author Bryan.Zhang
* @email weenyc31@163.com
* @Date 2020/4/1
*/
package com.yomahub.liteflow.test.nacos.cmp;
import com.yomahub.liteflow.core.NodeComponent;
import org.springframework.stereotype.Component;
@Component("c")
public class CCmp extends NodeComponent {
@Override
public void process() {
System.out.println("CCmp executed!");
}
}

View File

@ -0,0 +1,3 @@
#liteflow.rule-source-ext-data={"serverAddr":"192.168.10.147:8848"}
#liteflow.rule-source-ext-data={"serverAddr":"192.168.10.147:8848","dataId":"LiteFlow","group":"LITE_FLOW_GROUP"}
liteflow.rule-source-ext-data={"serverAddr":"192.168.10.147:8848","dataId":"LiteFlow","group":"LITE_FLOW_GROUP","namespace":"","username":"","password":""}

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<flow>
<chain name="chain1">
THEN(a, b, c);
</chain>
</flow>

View File

@ -22,5 +22,6 @@
<module>liteflow-testcase-el-script-groovy-springboot</module>
<module>liteflow-testcase-el-script-qlexpress-springboot</module>
<module>liteflow-testcase-el-zk-springboot</module>
<module>liteflow-testcase-el-nacos-springboot</module>
</modules>
</project>