前言
首先,感谢大家对上一篇文章[业务可视化-让你的流程图”Run”起来]的支持。
分享一下近期我对这个项目的一些改进。
问题&改进
问题1:
流程运行开始后,异步执行,无法同步等待流程运行结束。
改进方法:
修正后流程(黄色部分为修改点):
调用代码:
// 异步调用(默认)flow.start();// 或者flow.start(false);// 同步调用flow.start(true);
问题2:
工程需要自己下载编译,无法自动引用。
改进方法:
将代码发布到maven仓库,然后可以用下面的方法调用:
Maven
<!-- https://mvnrepository.com/artifact/io.github.nobuglady/ladybugflow --><dependency><groupId>io.github.nobuglady</groupId><artifactId>ladybugflow</artifactId><version>0.0.1</version></dependency>
Gradle
// https://mvnrepository.com/artifact/io.github.nobuglady/ladybugflowimplementation 'io.github.nobuglady:ladybugflow:0.0.1'
发布到maven仓库遇到的坑:
1. 自动发布到maven仓库后,无法release。
首先,在创建了maven仓库的账号,并且完成相关配置后,发布流程如下
a) 执行命令 mvn clean deploy
b) 登录sonatype仓库,选择Staging Repository,将发布的工程选中,选择close。
c) 登录sonatype仓库,选择Staging Repository,将发布的工程选中,选择release。
我遇到的问题:
步骤a)执行完毕正常结束后,在sonatype仓库中,在Staging Repository中看不到自己的工程。
但是搜索自己的工程可以看到已经上传的文件,也可以删除(release状态的文件应该不能删除)。
所以判断是没有自动release,但也没法手工release,也没有任何错误提示。
解决方法:
本地打包,手工将bundle.jar上传到Staging Repository,这样可以看到中间状态文件出的问题。
果然,在手工上传成功后,自动运行的一些校验提示了一些pom文件问题,这可能是导致之前没有自动release的原因。
本地打包方法:
a) 执行
mvn release:clean release:prepare
b) 在target目录会看到类似下面的文件
ladybugflow-0.0.2.jarladybugflow-0.0.2.jar.ascladybugflow-0.0.2.pomladybugflow-0.0.2.pom.ascladybugflow-0.0.2-javadoc.jarladybugflow-0.0.2-javadoc.jar.ascladybugflow-0.0.2-sources.jarladybugflow-0.0.2-sources.jar.asc
c)进入到target目录,运行下面命令来打包
jar -cvf bundle.jar ladybugflow*
d)将打包好的jar文件手工上传到sonatype仓库
e)在sonatype仓库等待自己上传的文件到close状态,检查没问题后,选择release。
2. 提示 can not upload bundle Because is xxxx is a RELEASE repository
解决方法:
在pom.xm的版本号中加入-SNAPSHOT,比如
<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>io.github.nobuglady</groupId><artifactId>ladybugflow</artifactId><packaging>jar</packaging><version>0.0.2-SNAPSHOT</version><name>ladybugflow</name>......
项目优点
优点,也是难点,但不是亮点。设计过程复杂(花了很长时间做改进),设计结果的话又极其简单(光看结果甚至会认为这个设计花不了一天)。
这种流程图设计的最大问题就是流程图状态的更新,比如等待前面的一个或多个节点运行结束后,启动自身节点。
第一版:每个节点提交到线程池后留下Future句柄,存起来。
后续节点运行前检查前面所有join到自己节点的Future句柄,是否完成。
可以阻塞检查,也可以sleep循环检查。
问题:
看似解决了问题,但隐患多多,比如所有的Future句柄都要存起来,那就涉及到这些东东的管理问题,想起来又兴奋又头大。
还有检查的时候是阻塞检查,还是sleep循环检查,还是。。。还是给每个节点加一个计数器,计数器清零则触发本节点执行。。。
改进:
将多线程转化为单线程或者可控的几个线程,把图(流程图)单独管理。
简单的说,是一个人(一个逻辑)单独的只负责更新图,根据每个节点的状态更新图。更新图后,输出后续要运行的节点给调用者。
这样就将节点运行,流程图状态分开管理。更新图的流程入口和出口分别对应两个队列:
入口:运行完毕的节点队列
出口:将要运行的节点队列
更新图的流程监听入口,得到一个消息(节点运行完毕)后,更新该节点对应的流程图,然后将后续要运行的节点输出给出口(将要运行的队列)。
节点的运行逻辑监听出口队列,然后怎么运行节点都可以了,在本地,在远程,在云端都无所谓,只要节点运行后告知入口队列,自己运行完毕,
则流程图会自动更新,并且往出口上发消息(后续要运行的节点),如下图所示:
这样设计的优点:
将多线程转化为单线程或者有限的几个线程处理,避免了高并发编程带来的各种问题和风险。
可以***对流程图模块进行升级,比如每条边加条件,根据条件进行更新,异常后对流程的更新,根据节点返回值进行更新,绑定动态逻辑等等,我可以专心的设计路程图更新的方法,不用考虑节点运行的事情。实现了流程图更新***。
可以***对节点运行模块进行升级,云端运行,api调用运行,shell运行,本地运行,分布式集群运行等等,不用考虑流程图怎么更新的问题。实现了节点运行***。
感谢您看文章读到这里。