• [介绍/入门] 华为云函数工作流FunctionGraph新手操作指南
    函数工作流(FunctionGraph)是华为云提供的一款无服务器(Serverless)计算服务,无服务器计算是一种托管服务,服务提供商会实时为你分配充足的资源,而不需要预留专用的服务器或容量,真正按实际使用付费.本文将给各位开发者带来华为云FunctionGraph的手把手初级教学,让没有接触过的开发者能够轻松上手体验。前提条件1.了解函数支持的编程语言,具体请参见支持的编程语言。2.创建程序包,具体请参见创建程序包。3.创建委托(可选,根据实际情况,确定是否需创建委托),具体请参见配置委托权限操作步骤一、登录华为云账号1.请注册华为云账号并完成实名认证,体验过程中请使用Chrome浏览器完成相关操作。华为云账号注册步骤请参考:cid:link_1实名认证操作步骤请参考:cid:link_0二、创建空白函数2.点击下方链接进入华为云FunctionGraph首页cid:link_23.点击“立即使用”4.进入控制台,点击右上角的“创建函数”5.选择创建空白函数中的“事件函数”任意填写函数名称,这里我们用“test” 其余参数不用修改,点击右下方“创建函数”6.页面跳转至代码配置页面,可以继续配置代码源。您可以根据所选的运行时语言Runtime,参见创建程序包,选择适合的方式进行代码源部署,完成后单击“部署”。代码若有修改,请修改完成后再次单击“部署”,重新部署代码。7. 下滑页面查看代码属性代码属性展示最新部署代码的大小及上次修改时间8. 下滑页面查看基本信息函数创建完成后,各语言默认内存和执行超时时间如图4所示,请根据实际业务评估,若需修改“函数执行入口”、“内存(MB)”“执行超时时间(秒)”,可单击“编辑”,在常规设置中修改配置信息,具体请参见配置常规信息。以上就是华为云FunctionGraph的基础教程,除此之外,还可以使用示例模板创建函数;使用容器镜像创建函数等等。感兴趣的开发者赶快戳这里>>体验华为云FunctionGraph
  • [问题求助] 函数互调有一行代码没看懂
    函数互调的开发文档里有一行没看懂:cid:link_0这里的主机名应该填什么?
  • [活动分享] 【DevRun】华为云&昇腾联合云上应用开发、AI训练营来咯~~
    Serverless被业界称为云计算的下一个10年,“Serverless 简化了云计算的编程,其代表了程序员生产力的又一次的变革,如编程语言从汇编时代演变为高级语言时代。本体验营将带你了解无服务计算概念,学会如何基于Severless技术构建可用于个人学习以及生产开发的个人网站,一站式高效体验华为的云端应用开发!>> 点击快速报名活动<<
  • [技术干货] 三分钟完成静态网站托管 ——一行代码秒上云实践
    1 前言无服务器托管静态网站,你的第一个Serverless实战,快来体验吧!对更多云上实践感兴趣的小伙伴,欢迎扫描文末二维码加入我们的实践群,完成每周一练~2 操作流程创建函数修改代码在线调试创建触发器访问页面删除函数3 操作指导3.1 创建函数登录华为云后,按“产品”-“计算”-“函数工作流FunctionGraph”路径,进入华为云函数工作流FunctionGraph平台首页。华为云官网:cid:link_1点击“立即使用”按钮,进入FunctionGraph首页。将区域切换至“广州”,点击“创建函数”按钮在创建函数页,按如下参数配置项目选择“创建空白函数”函数类型:事件函数区域:华南-广州函数名称:homepage运行时:Node.js 14.18点击“创建函数”完成创建3.2 修改函数代码访问开源代码仓:cid:link_0选择“函数工作流静态网站托管-homepage”文件夹打开“index.js”文件,复制代码回到FunctionGraph,点击函数页“代码”,打开“index.js”文件,粘贴代码,点击“部署”按钮。访问代码仓,打开“homepage.html”文件,复制代码点击“文件”-“新建文件”,重命名为“homepage.html”,将代码仓内“homepage.html”内代码复制进去后,点击“部署”3.3 在线调试点击“测试”,右侧出现“执行成功”的结果反馈。3.4 创建触发器在函数概述页,点击“创建触发器”。在创建触发器页面,完成如下配置:触发器类型:API网关服务(APIG)API名称:API_homepage分组:需自行创建,刷新后可选(详见下文)安全认证:None请求协议:HTTPS其他项默认点击“创建分组”,进入API网关,自定义分组名,点击“确定”即可完成创建。在创建触发器页面,点击“确定”按钮即可完成创建,如下。3.5 访问页面复制触发器中“调用URL”,在浏览器内进行访问,即可访问个人主页。3.6 删除函数实验结束可删除触发器,删除函数,防止大量用户继续访问造成资源消耗。欢迎对云上实践感兴趣的小伙伴,扫描二维码加入我们的每日一练~
  • [技术干货] Serverless六步构建全栈网站
    1 前言:Serverless怎么玩?听一千道一万不如亲手来实践,跟着我们以华为云Serverless实践FunctionGraph来免费体验一下六步构建全栈网站吧!五分钟就完成的应用上云,你值得拥有 !如果您对更多Serverrless实践感兴趣,还可以扫描文末二维码,加入我们一起体验华为云最佳实践!下面让我们开始吧!2 实践流程创建函数上传代码测试函数创建触发器访问应用删除函数3 操作指导3.1 创建函数登录华为云后,按“产品”-“计算”-“函数工作流FunctionGraph”路径,进入华为云函数工作流FunctionGraph平台首页。华为云官网:cid:link_2点击“立即使用”按钮,进入FunctionGraph首页。将区域切换至“广州”,点击“创建函数”按钮。在创建函数页,按如下参数配置项目选择“创建空白函数”函数类型:HTTP函数区域:华南-广州函数名称:web02点击“创建函数”完成创建3.2 上传代码前往代码仓,选择“函数工作流构建全栈网站”文件夹,下载web2.zip文件代码仓地址:cid:link_1前往FunctionGraph函数页面,依次点击“代码”-“上传至”-“Zip文件”,上传从代码仓下载的“web2”文件包3.3 测试函数为更好的观测函数的调用结果,先开通FunctionGraph日志上传LTS服务在函数详情页面,依次点击“监控”-“日志”,点击“开通”。点击“代码”,点击“配置测试事件”,点击“创建”完成测试事件配置。点击“测试”,返回执行结果3.4 创建触发器在函数概述页点击“创建触发器”在弹出的创建触发器页,完成如下配置:触发器类型:API网关服务(APIG)API名称:API_web02分组:先自行创建,刷新后可选(详见下文)安全认证:None请求协议:HTTPS其他项默认点击“创建分组”,在API网关页创建分组设置分组名称为“APIGroup_web02”(可自定义),点击确定完成创建。点击“我知道了”后,返回函数页。刷新创建触发器页“分组”,选择刚刚创建的分组“APIGroup_web02”,点击确定完成创建3.5 访问应用访问链接:APIG调用URL+/web2/excalidraw/,即可访问应用。3.6 删除函数实验结束可删除触发器和函数,防止大量用户继续访问造成资源消耗。如果您想要体验更多的华为云云上最佳实践,快来扫码加入我们把!另外我们还会不定期在群内发布开源项目的悬赏任务,等你来挑战!
  • [区域初赛赛题问题] 京津东北赛区复赛名单跨赛区组队
    不是要求不同赛区不能组队吗,京津东北赛区复赛晋级名单有两个队有跨赛区学校队员
  • [常见FAQ] 未组队就不能提交了吗
    为什么报名了,没组队连提交都不让呢
  • [技术干货] flowable 从入门到精通
    一、Flowable简介1、Flowable是什么Flowable是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义(用于定义流程的行业XML标准), 创建这些流程定义的流程实例,进行查询,访问运行中或历史的流程实例与相关数据,等等。这个章节将用一个可以在你自己的开发环境中使用的例子,逐步介绍各种概念与API。Flowable可以十分灵活地加入你的应用/服务/构架。可以将JAR形式发布的Flowable库加入应用或服务,来嵌入引擎。 以JAR形式发布使Flowable可以轻易加入任何Java环境:Java SE;Tomcat、Jetty或Spring之类的servlet容器;JBoss或WebSphere之类的Java EE服务器,等等。 另外,也可以使用Flowable REST API进行HTTP调用。也有许多Flowable应用(Flowable Modeler, Flowable Admin, Flowable IDM 与 Flowable Task),提供了直接可用的UI示例,可以使用流程与任务。所有使用Flowable方法的共同点是核心引擎。核心引擎是一组服务的集合,并提供管理与执行业务流程的API。 下面的教程从设置与使用核心引擎的介绍开始。后续章节都建立在之前章节中获取的知识之上。2、Flowable与ActivitiFlowable,2016年基于Activiti诞生。二、开始1、构建命令行程序我们将构建的例子是一个简单的请假(holiday request)流程:雇员(employee)申请几天的假期经理(manager)批准或驳回申请我们会模拟将申请注册到某个外部系统,并给雇员发送结果邮件1.1、创建流程引擎1.1.1、创建maven项目创建一个名为holiday-request的maven项目,添加依赖: <!--Flowable流程引擎--> <dependency> <groupId>org.flowable</groupId> <artifactId>flowable-engine</artifactId> <version>6.3.0</version> </dependency> <!--MySQL驱动,这里采用MySQL数据库,如果采用其它数据库,需要引入对应的依赖。--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.15</version> </dependency>1.1.2、创建数据库表格创建一个数据库flowable_demo。创建一个普通的Java类:HolidayRequest/** * @Author 三分恶 * @Date 2020/5/2 * @Description 创建表格 */public class HolidayRequest { public static void main(String[] args) { //1、创建ProcessEngineConfiguration实例,该实例可以配置与调整流程引擎的设置 ProcessEngineConfiguration cfg=new StandaloneProcessEngineConfiguration() //2、通常采用xml配置文件创建ProcessEngineConfiguration,这里直接采用代码的方式 //3、配置数据库相关参数 .setJdbcUrl("jdbc:mysql://localhost:3306/flowable_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT+8&nullCatalogMeansCurrent=true") .setJdbcUsername("root") .setJdbcPassword("root") .setJdbcDriver("com.mysql.jdbc.Driver") .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); //4、初始化ProcessEngine流程引擎实例 ProcessEngine processEngine=cfg.buildProcessEngine(); }}1.1.3、运行运行该类,会发现在数据库flowable_demo中创建了34个表:1.1.4、创建的表格说明flowable命名规则:ACT_RE_* :’ RE ’表示repository(存储)。RepositoryService接口操作的表。带此前缀的表包含的是静态信息,如,流程定义,流程的资源(图片,规则等)。ACT_RU_* :’ RU ’表示runtime。这是运行时的表存储着流程变量,用户任务,变量,职责(job)等运行时的数据。flowable只存储实例执行期间的运行时数据,当流程实例结束时,将删除这些记录。这就保证了这些运行时的表小且快。ACT_ID_* : ’ ID ’表示identity(组织机构)。这些表包含标识的信息,如用户,用户组,等等。ACT_HI_* : ’ HI ’表示history。就是这些表包含着历史的相关数据,如结束的流程实例,变量,任务,等等。ACT_GE_* : 普通数据,各种情况都使用的数据。34张表说明:表分类表名表说明一般数据(2)ACT_GE_BYTEARRAY通用的流程定义和流程资源ACT_GE_PROPERTY系统相关属性流程历史记录(8)ACT_HI_ACTINST历史的流程实例ACT_HI_ATTACHMENT历史的流程附件ACT_HI_COMMENT历史的说明性信息ACT_HI_DETAIL历史的流程运行中的细节信息ACT_HI_IDENTITYLINK历史的流程运行过程中用户关系ACT_HI_PROCINST历史的流程实例ACT_HI_TASKINST历史的任务实例ACT_HI_VARINST历史的流程运行中的变量信息用户用户组表(9)ACT_ID_BYTEARRAY二进制数据表ACT_ID_GROUP用户组信息表ACT_ID_INFO用户信息详情表ACT_ID_MEMBERSHIP人与组关系表ACT_ID_PRIV权限表ACT_ID_PRIV_MAPPING用户或组权限关系表ACT_ID_PROPERTY属性表ACT_ID_TOKEN系统登录日志表ACT_ID_USER用户表流程定义表(3)ACT_RE_DEPLOYMENT部署单元信息ACT_RE_MODEL模型信息ACT_RE_PROCDEF已部署的流程定义运行实例表(10)ACT_RU_DEADLETTER_JOB正在运行的任务表ACT_RU_EVENT_SUBSCR运行时事件ACT_RU_EXECUTION运行时流程执行实例ACT_RU_HISTORY_JOB历史作业表ACT_RU_IDENTITYLINK运行时用户关系信息ACT_RU_JOB运行时作业表ACT_RU_SUSPENDED_JOB暂停作业表ACT_RU_TASK运行时任务表ACT_RU_TIMER_JOB定时作业表ACT_RU_VARIABLE运行时变量表其他表(2)ACT_EVT_LOG事件日志表ACT_PROCDEF_INFO流程定义信息1.1.4、日志配置在上面的运行中,同时可以看到,控制台有报错的信息,这是日志没有正确地配置:Flowable使用SLF4J作为内部日志框架。我们使用log4j作为SLF4J的实现。因此在pom.xml文件中添加下列依赖:<dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version></dependency><dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version></dependency>在 src/resouce目录下新建log4j的配置文件log4j.properties:log4j.rootLogger=DEBUG, CAlog4j.appender.CA=org.apache.log4j.ConsoleAppenderlog4j.appender.CA.layout=org.apache.log4j.PatternLayoutlog4j.appender.CA.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n再次运行,可以看到关于引擎启动与创建数据库表结构的提示日志:1.2、部署流程定义要构建的流程是一个非常简单的请假流程。Flowable引擎需要流程定义为BPMN 2.0格式,这是一个业界广泛接受的XML标准。在Flowable术语中,我们将其称为一个流程定义(process definition)。一个流程定义可以启动多个流程实例(process instance)。流程定义可以看做是重复执行流程的蓝图。 在这个例子中,流程定义定义了请假的各个步骤,而一个流程实例对应某个雇员提出的一个请假申请。BPMN 2.0存储为XML,并包含可视化的部分:使用标准方式定义了每个步骤类型(人工任务,自动服务调用,等等)如何呈现,以及如何互相连接。这样BPMN 2.0标准使技术人员与业务人员能用双方都能理解的方式交流业务流程。我们要使用的流程定义为:流程定义的说明:我们假定启动流程需要提供一些信息,例如雇员名字、请假时长以及说明。当然,这些可以单独建模为流程中的第一步。 但是如果将它们作为流程的“输入信息”,就能保证只有在实际请求时才会建立一个流程实例。否则(将提交作为流程的第一步),用户可能在提交之前改变主意并取消,但流程实例已经创建了。 在某些场景中,就可能影响重要的指标(例如启动了多少申请,但还未完成),取决于业务目标。左侧的圆圈叫做启动事件(start event)。这是一个流程实例的起点。第一个矩形是一个用户任务(user task)。这是流程中人类用户操作的步骤。在这个例子中,经理需要批准或驳回申请。取决于经理的决定,排他网关(exclusive gateway) (带叉的菱形)会将流程实例路由至批准或驳回路径。如果批准,则需要将申请注册至某个外部系统,并跟着另一个用户任务,将经理的决定通知给申请人。当然也可以改为发送邮件。如果驳回,则为雇员发送一封邮件通知他。一般来说,这样的流程定义使用可视化建模工具建立,如Flowable Designer(Eclipse)或Flowable Web Modeler(Web应用)。这里我们直接撰写XML,以熟悉BPMN 2.0及其概念。以下是与上面展示的流程图对应的BPMN 2.0 XML。这里只包含了“流程部分”。如果使用图形化建模工具,实际的XML文件还将包含“可视化部分”,用于描述图形信息,如流程定义中各个元素的坐标(所有的图形化信息包含在XML的BPMNDiagram标签中,作为definitions标签的子元素)。在src/main/resources文件夹下创建为holiday-request.bpmn20.xml文件:<?xml version="1.0" encoding="utf-8" ?><definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:flowable="http://flowable.org/bpmn" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.flowable.org/processdef"> <process id="holiday-request" name="Holiday Request" isExecutable="true"> <!--开始事件:流程实例的起点--> <startEvent id="startEvent"/> <!--顺序流:执行时会从一个活动流向另一个活动--> <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/> <!--用户任务:需要人工来进行操作--> <userTask id="approveTask" name="Approve or reject request"/> <sequenceFlow sourceRef="approveTask" targetRef="decision"/> <!--排他网关--> <exclusiveGateway id="decision"/> <sequenceFlow sourceRef="decision" targetRef="externalSystemCall"> <!--顺序流条件:以表达式(expression)的形式定义了条件(condition) --> <conditionExpression xsi:type="tFormalExpression"> <!--条件表达式:是${approved == true}的简写--> <![CDATA[ ${approved} ]]> </conditionExpression> </sequenceFlow> <sequenceFlow sourceRef="decision" targetRef="sendRejectionMail"> <conditionExpression xsi:type="tFormalExpression"> <![CDATA[ ${!approved} ]]> </conditionExpression> </sequenceFlow> <!--服务任务,一个自动活动,它会调用一些服务--> <serviceTask id="externalSystemCall" name="Enter holidays in external system" flowable:class="edu.hpu.process.CallExternalSystemDelegate"/> <userTask id="holidayApprovedTask" name="Holiday Approve!"/> <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/> <serviceTask id="sendRejectionMail" name="Send out rejection email" flowable:class="edu.hpu.process.SendRejectionMail"/> <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/> <!--结束事件--> <endEvent id="approveEnd"/> <endEvent id="rejectEnd"/> </process></definitions>每一个步骤(在BPMN 2.0术语中称作活动(activity))都有一个id属性,为其提供一个在XML文件中唯一的标识符。所有的活动都可以设置一个名字,以提高流程图的可读性。活动之间通过顺序流(sequence flow)连接,在流程图中是一个有向箭头。在执行流程实例时,执行(execution)会从启动事件沿着顺序流流向下一个活动。离开排他网关(带有X的菱形)的顺序流很特别:都以表达式(expression)的形式定义了条件(condition) 。当流程实例的执行到达这个网关时,会计算条件,并使用第一个计算为true的顺序流。这就是排他的含义:只选择一个。当然如果需要不同的路由策略,可以使用其他类型的网关。这里用作条件的表达式为approved,这是{approved == true}的简写。变量’approved’被称作流程变量(process variable)。流程变量是持久化的数据,与流程实例存储在一起,并可以在流程实例的生命周期中使用。在这个例子里,我们需要在特定的地方(当经理用户任务提交时,或者以Flowable的术语来说,完成(complete)时)设置这个流程变量,因为这不是流程实例启动时就能获取的数据。现在我们已经有了流程BPMN 2.0 XML文件,下来需要将它部署(deploy)到引擎中。部署一个流程定义意味着:流程引擎会将XML文件存储在数据库中,这样可以在需要的时候获取它。流程定义转换为内部的、可执行的对象模型,这样使用它就可以启动流程实例。将流程定义部署至Flowable引擎,需要使用RepositoryService,其可以从ProcessEngine对象获取。使用RepositoryService,可以通过XML文件的路径创建一个新的部署(Deployment),并调用deploy()方法实际执行: //创建RepositoryService实例 RepositoryService repositoryService=processEngine.getRepositoryService(); //加载流程 Deployment deployment=repositoryService.createDeployment() .addClasspathResource("holiday-request.bpmn20.xml") .deploy();我们现在可以通过API查询验证已经部署在引擎中的流程定义。通过RepositoryService创建的ProcessDefinitionQuery对象实现。 //查询流程定义 ProcessDefinition processDefinition=repositoryService.createProcessDefinitionQuery() .deploymentId(deployment.getId()) .singleResult(); System.out.println("Found process definition : "+processDefinition.getName());运行:xml文件已经存储进了数据库:1.3、启动流程实例现在已经在流程引擎中部署了流程定义,因此可以使用这个流程定义作为“蓝图”启动流程实例。要启动流程实例,需要提供一些初始化流程变量。一般来说,可以通过呈现给用户的表单,或者在流程由其他系统自动触发时通过REST API,来获取这些变量。在这个例子里,我们简化为使用java.util.Scanner类在命令行输入一些数据: //1、获取流程初始化变量 Scanner scanner = new Scanner(System.in); System.out.println("Who are you?"); String employee = scanner.nextLine(); System.out.println("How many holidays do you want to request?"); Integer nrOfHolidays = Integer.valueOf(scanner.nextLine()); System.out.println("Why do you need them?"); String description = scanner.nextLine();接下来,我们使用RuntimeService启动一个流程实例。收集的数据作为一个java.util.Map实例传递,其中的键就是之后用于获取变量的标识符。这个流程实例使用key启动(还有其它方式)。这个key就是BPMN 2.0 XML文件中设置的id属性,在这个例子里是holiday-request。<process id="holiday-request" name="Holiday Request" isExecutable="true"> //2、使用RuntimeService启动一个流程实例 RuntimeService runtimeService=processEngine.getRuntimeService(); Map<String, Object> variables = new HashMap<String, Object>(); variables.put("employee", employee); variables.put("nrOfHolidays", nrOfHolidays); variables.put("description", description); ProcessInstance processInstance=runtimeService.startProcessInstanceByKey("holiday-request",variables);在流程实例启动后,会创建一个执行(execution),并将其放在启动事件上。从这里开始,这个执行会沿着顺序流移动到经理审批的用户任务,并执行用户任务行为。这个行为将在数据库中创建一个任务,该任务可以之后使用查询找到。用户任务是一个等待状态(wait state),引擎会停止执行,返回API调用处。输入流程初始化变量:将数据插入数据库中向数据库中插入了数据:1.4、Flowable中的事务在Flowable中,数据库事务扮演了关键角色,用于保证数据一致性,并解决并发问题。当调用Flowable API时,默认情况下,所有操作都是同步的,并处于同一个事务下。这意味着,当方法调用返回时,会启动并提交一个事务。流程启动后,会有一个数据库事务从流程实例启动时持续到下一个等待状态。在这个例子里,指的是第一个用户任务。当引擎到达这个用户任务时,状态会持久化至数据库,提交事务,并返回API调用处。在Flowable中,当一个流程实例运行时,总会有一个数据库事务从前一个等待状态持续到下一个等待状态。数据持久化之后,可能在数据库中保存很长时间,甚至几年,直到某个API调用使流程实例继续执行。请注意当流程处在等待状态时,不会消耗任何计算或内存资源,直到下一次APi调用。在这个例子中,当第一个用户任务完成时,会启动一个数据库事务,从用户任务开始,经过排他网关(自动逻辑),直到第二个用户任务。或通过另一条路径直接到达结束。1.5、查询与完成任务在更实际的应用中,会为雇员及经理提供用户界面,让他们可以登录并查看任务列表。其中可以看到作为流程变量存储的流程实例数据,并决定如何操作任务。在这个例子中,我们通过执行API调用来模拟任务列表,通常这些API都是由UI驱动的服务在后台调用的。我们还没有为用户任务配置办理人。将第一个任务指派给"经理(managers)"组,而第二个用户任务指派给请假申请的提交人。 <!--将任务指派给经理组--> <userTask id="approveTask" name="Approve or reject request" flowable:candidateGroups="managers"/> <!--指派给请假审批的审批人,${employee}使用流程变量动态指派,在流程实例启动时传递--> <userTask id="holidayApprovedTask" name="Holiday Approve!" flowable:assignee="${employee}"/>要获得实际的任务列表,需要通过TaskService创建一个TaskQuery。这个查询配置为只返回’managers’组的任务: //通过TaskService查询 manager 组的任务 TaskService taskService=processEngine.getTaskService(); List<Task> tasks=taskService.createTaskQuery().taskCandidateGroup("managers").list(); System.out.println("You have " + tasks.size() + " tasks:"); for (int i=0; i<tasks.size(); i++) { System.out.println((i+1) + ") " + tasks.get(i).getName()); }使用集合下标获取特定流程实例的变量,在控制台输出 //使用集合下标获取特定流程实例的变量,在控制台输出 System.out.println("Which task would you like to complete?"); int taskIndex = Integer.valueOf(scanner.nextLine()); Task task=tasks.get(taskIndex-1); Map<String,Object> processVariables=taskService.getVariables(task.getId()); System.out.println(processVariables.get("employee") + " wants " + processVariables.get("nrOfHolidays") + " of holidays. Do you approve this?");经理现在就可以完成任务了。在实际开发中,通常由用户提交一个表单。表单中的数据作为流程变量传递。在这里,我们在完成任务时传递带有’approved’变量(这个名字很重要,因为之后会在顺序流的条件中使用)的map来模拟: //经理完成任务 boolean approved=scanner.nextLine().toLowerCase().equals("y"); variables = new HashMap<String, Object>(); variables.put("approved", approved); //任务完成,并会在离开排他网关的两条路径中,基于’approved ’流程变量选择一条 taskService.complete(task.getId(),variables);现在还缺最后一点,服务任务调用的服务没有实现: <!--服务任务,一个自动活动,它会调用一些服务--> <serviceTask id="externalSystemCall" name="Enter holidays in external system" flowable:class="edu.hpu.process.CallExternalSystemDelegate"/>创建一个类,实现JavaDelegate接口,实现execute方法,这个方法可以写很多业务逻辑,这里我们只是是在控制台打印输出一些内容:/** * @Author 三分恶 * @Date 2020/5/3 * @Description */public class CallExternalSystemDelegate implements JavaDelegate { public void execute(DelegateExecution delegateExecution) { System.out.println("Calling the external system for employee " + delegateExecution.getVariable("employee")); }}运行:启动流程:查看任务完成任务执行自动逻辑至此,一个模拟请假流程就完成了。1.6、使用历史数据选择使用Flowable这样的流程引擎的原因之一,是它可以自动存储所有流程实例的审计数据或历史数据。这些数据可以用于创建报告,深入展现组织运行的情况,瓶颈在哪里,等等。从ProcessEngine获取HistoryService,并创建历史活动(historical activities)的查询。 //获取HistoryService实例 HistoryService historyService=processEngine.getHistoryService(); //添加查询条件 List<HistoricActivityInstance> activities = historyService.createHistoricActivityInstanceQuery() //选择特定实例 .processInstanceId(processInstance.getId()) //选择已完成的 .finished() //根据实例完成时间升序排列 .orderByHistoricActivityInstanceEndTime().asc() .list(); for (HistoricActivityInstance activity : activities) { System.out.println(activity.getActivityId() + " took " + activity.getDurationInMillis() + " milliseconds"); }转自 https://www.cnblogs.com/three-fighter/p/12822062.html
  • [技术干货] Flowable初体验——开始
    1.Flowable是什么?        Flowable是一个使用Java编写的轻量级业务流程引擎。Flowable流程引擎可用于部署BPMN 2.0流程定义(用于定义流程的行业XML标准), 创建这些流程定义的流程实例,进行查询,访问运行中或历史的流程实例与相关数据,等等。        Flowable可以十分灵活地加入你的应用/服务/构架。可以将JAR形式发布的Flowable库加入应用或服务,来嵌入引擎。 以JAR形式发布使Flowable可以轻易加入任何Java环境:Java SE;Tomcat、Jetty或Spring之类的servlet容器;JBoss或WebSphere之类的Java EE服务器,等等。 另外,也可以使用Flowable REST API进行HTTP调用。也有许多Flowable应用(Flowable Modeler, Flowable Admin, Flowable IDM 与 Flowable Task),提供了直接可用的UI示例,可以使用流程与任务。        所有使用Flowable方法的共同点是核心引擎。核心引擎是一组服务的集合,并提供管理与执行业务流程的API。 下面的教程从设置与使用核心引擎的介绍开始。后续章节都建立在之前章节中获取的知识之上。(摘自Flowable用户手册)2.Flowabel和Activiti的关系        Flowable是Activiti(Alfresco持有的注册商标)的fork。3.准备开始3.1 创建一个Maven工程我习惯使用IDEA,这里就用IDEA里的截图了。我们打开file->new->project...如下图所示: 到此,我们就创建了一个空的maven项目。3.2 添加依赖一个是Flowable的依赖,一个是数据的依赖。    <dependencies>            <dependency>                <groupId>org.flowable</groupId>                <artifactId>flowable-engine</artifactId>                <version>6.3.0</version>            </dependency>            <dependency>                <groupId>mysql</groupId>                <artifactId>mysql-connector-java</artifactId>                <version>8.0.29</version>            </dependency>        </dependencies>记得刷新maven引入依赖。3.3  创建Java类我这里直接就用项目生成自带的一个类了。3.3.1 获取流程引擎对象    public void processEngine(){            // 获取ProcessEngineConfiguration对象            ProcessEngineConfiguration configuration = new StandaloneProcessEngineConfiguration();            // 配置相关的数据库连接信息            configuration                    .setJdbcDriver("com.mysql.cj.jdbc.Driver")                    .setJdbcUsername("root")                    .setJdbcPassword("123456")                    .setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC")                    // 如果数据库中的表结构不存在就新建                    .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);            // 通过ProcessEngineConfiguration构建我们需要的ProcessEngine            ProcessEngine processEngine = configuration.buildProcessEngine();        }此时,运行这个方法。我的控制台报错了,具体信息如下: 解决方法:添加nullCatalogMeansCurrent=true,设置只查询当前连接的schema库即可。具体修改语句:.setJdbcUrl("jdbc:mysql://localhost:3306/flowable-learn?serverTimezone=UTC&nullCatalogMeansCurrent=true")此时呢,我们发现数据库中已经生成了相应的表了,这就表明成功了。如果出现日志报错的话,可以添加相应的依赖,配置文件即可。3.3.2 部署流程定义        我们要构建的流程是一个非常简单的请假流程。Flowable引擎需要流程定义为BPMN 2.0格式,这是一个业界广泛接受的XML标准。 在Flowable术语中,我们将其称为一个流程定义(process definition)。一个流程定义可以启动多个流程实例(process instance)。流程定义可以看做是重复执行流程的蓝图。 在这个例子中,流程定义定义了请假的各个步骤,而一个流程实例对应某个雇员提出的一个请假申请。        BPMN 2.0存储为XML,并包含可视化的部分:使用标准方式定义了每个步骤类型(人工任务,自动服务调用,等等)如何呈现,以及如何互相连接。这样BPMN 2.0标准使技术人员与业务人员能用双方都能理解的方式交流业务流程。        我们要使用的流程定义为:这个流程应该已经十分自我解释了。但为了明确起见,说明一下几个要点:    我们假定启动流程需要提供一些信息,例如雇员名字、请假时长以及说明。当然,这些可以单独建模为流程中的第一步。 但是如果将它们作为流程的“输入信息”,就能保证只有在实际请求时才会建立一个流程实例。否则(将提交作为流程的第一步),用户可能在提交之前改变主意并取消,但流程实例已经创建了。 在某些场景中,就可能影响重要的指标(例如启动了多少申请,但还未完成),取决于业务目标。    左侧的圆圈叫做启动事件(start event)。这是一个流程实例的起点。    第一个矩形是一个用户任务(user task)。这是流程中人类用户操作的步骤。在这个例子中,经理需要批准或驳回申请。    取决于经理的决定,排他网关(exclusive gateway) (带叉的菱形)会将流程实例路由至批准或驳回路径。    如果批准,则需要将申请注册至某个外部系统,并跟着另一个用户任务,将经理的决定通知给申请人。当然也可以改为发送邮件。    如果驳回,则为雇员发送一封邮件通知他。一般来说,这样的流程定义使用可视化建模工具建立,如Flowable Designer(Eclipse)或Flowable Web Modeler(Web应用)。将下面的XML保存在src/main/resources文件夹下名为holiday-request.bpmn20.xml的文件中。    <?xml version="1.0" encoding="UTF-8"?>    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:xsd="http://www.w3.org/2001/XMLSchema"      xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"      xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC"      xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI"      xmlns:flowable="http://flowable.org/bpmn"      typeLanguage="http://www.w3.org/2001/XMLSchema"      expressionLanguage="http://www.w3.org/1999/XPath"      targetNamespace="http://www.flowable.org/processdef">           <process id="holidayRequest" name="Holiday Request" isExecutable="true">             <startEvent id="startEvent"/>        <sequenceFlow sourceRef="startEvent" targetRef="approveTask"/>             <userTask id="approveTask" name="Approve or reject request"/>        <sequenceFlow sourceRef="approveTask" targetRef="decision"/>             <exclusiveGateway id="decision"/>        <sequenceFlow sourceRef="decision" targetRef="externalSystemCall">          <conditionExpression xsi:type="tFormalExpression">            <![CDATA[              ${approved}            ]]>          </conditionExpression>        </sequenceFlow>        <sequenceFlow  sourceRef="decision" targetRef="sendRejectionMail">          <conditionExpression xsi:type="tFormalExpression">            <![CDATA[              ${!approved}            ]]>          </conditionExpression>        </sequenceFlow>             <serviceTask id="externalSystemCall" name="Enter holidays in external system"            flowable:class="org.flowable.CallExternalSystemDelegate"/>        <sequenceFlow sourceRef="externalSystemCall" targetRef="holidayApprovedTask"/>             <userTask id="holidayApprovedTask" name="Holiday approved"/>        <sequenceFlow sourceRef="holidayApprovedTask" targetRef="approveEnd"/>             <serviceTask id="sendRejectionMail" name="Send out rejection email"            flowable:class="org.flowable.SendRejectionMail"/>        <sequenceFlow sourceRef="sendRejectionMail" targetRef="rejectEnd"/>             <endEvent id="approveEnd"/>             <endEvent id="rejectEnd"/>           </process>         </definitions>        每一个步骤(在BPMN 2.0术语中称作活动(activity))都有一个id属性,为其提供一个在XML文件中唯一的标识符。所有的活动都可以设置一个名字,以提高流程图的可读性。        活动之间通过顺序流(sequence flow)连接,在流程图中是一个有向箭头。在执行流程实例时,执行(execution)会从启动事件沿着顺序流流向下一个活动。        离开排他网关(带有X的菱形)的顺序流很特别:都以表达式(expression)的形式定义了条件(condition) (见第25至32行)。当流程实例的执行到达这个网关时,会计算条件,并使用第一个计算为true的顺序流。这就是排他的含义:只选择一个。当然如果需要不同的路由策略,可以使用其他类型的网关。        这里用作条件的表达式为${approved},这是${approved == true}的简写。变量’approved’被称作流程变量(process variable)。流程变量是持久化的数据,与流程实例存储在一起,并可以在流程实例的生命周期中使用。在这个例子里,我们需要在特定的地方(当经理用户任务提交时,或者以Flowable的术语来说,完成(complete)时)设置这个流程变量,因为这不是流程实例启动时就能获取的数据。现在我们已经有了流程BPMN 2.0 XML文件,下来需要将它部署(deploy)到引擎中。————————————————版权声明:本文为CSDN博主「不想躺平的咸鱼」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/weixin_47541263/article/details/127694256
  • [问题求助] 请教SDC相机,预警订阅接口问题
    2023-03-13 17:17:10.435 [Thread-15] INFO  c.g.iot.vmp.hw.controller.WarningController:258 - ---->常规获取预警:{"result":"success","data":{"alarm_list":[{"time":"03/13/2023 17:17:09","channel_alarm":[{"channel":"CH2","int_alarm":{"alarm_val":true,"int_subtype":"Third Part Alog"}}]},{"time":"03/13/2023 17:17:09","channel_alarm":[{"channel":"CH1","record_flag":{}},{"channel":"CH2","record_flag":{}},{"channel":"CH3","record_flag":{}},{"channel":"CH4","record_flag":{}},{"channel":"CH5","record_flag":{}},{"channel":"CH6","record_flag":{}},{"channel":"CH7","record_flag":{}},{"channel":"CH8","record_flag":{}}]}],"reader_id":6,"sequence":131,"lap_number":0}}具体描述如附件,请大神支持下;
  • [问题求助] 都处理了半个小时了,还没变状态?
    都处理了半个小时了,还没变状态?请教一下,有的用手机号码注册的apple账户,没有邮箱,所以无法在testflight中进行邀请测试,该如何处理这样的账号呢?
  • [技术干货] iOS应用发布ITMS-90704错误解决
    iOS应用发布ITMS-90704错误解决今天第一次用XCode 9 GM版打包上传应用。貌似上传的过程更简单了。选择 “Automatically manage signing” (自动管理签名)后它就直接显示一个汇总信息列表,然后开始上传了,比以前简化了一两个步骤。不过第一次遇到这个 ITMS-90704 错误:error它显示是Warning,却又告诉你操作失败。错误信息如下:WARNING ITMS-90704: "Missing Marketing Icon. iOS Apps must include a 1024x1024px Marketing Icon in PNG format. Apps that do not include the Marketing Icon cannot be submitted for App Review or Beta App Review."大意是说,iOS 应用现在必须包含一个1024*1024的PNG格式的图标。没有这个图标的应用将不能提交应用审核,也不能提交 Beta 测试审核。好吧,看来 iOS 应用现在得把这个大图标放在应用中了。solution解决起来也简单。在图标 Asset 中放入1024* 1024的版本重新打包上传就好了。第一次遇到这个90704错误。记录下来。If you encounter the ITMS-90704 error when publishing your iOS application, you can use the appuploader tool to resolve it. This error is typically caused by a mismatch between the bundle identifier in your app and the one you specified in your App Store Connect account. To fix the error, follow these steps:Open the appuploader tool and log in with your Apple ID.Choose the "Packages" tab and select your app.Click on the "Metadata" button and ensure that the "Bundle ID" field matches the one in your App Store Connect account.If the bundle identifier is correct, go to the "Builds" tab and select the build that you want to publish.Click on the "Metadata" button and ensure that the "Bundle ID" field matches the one in your App Store Connect account.If the bundle identifier is correct, try uploading your app again.By following these steps, you should be able to successfully publish your iOS app without encountering the ITMS-90704 error. If you continue to have issues, you may want to consult with Apple Developer Support for further assistance.
  • 24r255
    案例链接:cid:link_0
  • 使用 FunctionGraph 快速构建自己的“ChatGPT”
    作者ChatGPT    果宝    历川拥抱Serverless,释放生产力点击体验 函数工作流 FunctionGraph新一代Serverless函数计算与编排服务一、背景ChatGPT是一个基于GPT-3模型的聊天机器人,可以与用户进行自然、流畅和有趣的对话。ChatGPT可以理解和使用多种语言,如英语、中文、日语、西班牙语、法语或德语;还可以根据用户的兴趣和需求,提供相关建议和创意内容,如诗歌、故事、代码、歌词等。ChatGPT是一个强大而灵活的工具,可以用于娱乐、学习或工作。但是在国内使用ChatGPT有些不便,是否可以基于OpenAI开放的API做一个给自己或者同事们使用的聊天机器人,甚至集成到更多的场景…. 效果如下:二、方案选型说干就干,我们先从做一个自己的机器人开始,首先我们从OpenAI获取用于鉴权的秘钥。然后写一个请求OpenAI接口的代码,并写一个web服务接口开放出去,再搭配一个交互用的前端即可。看起来是1小时的工作量,但是如何部署这个服务呢? 购买一个云服务器再安装环境或者配置容器也太麻烦了,于是我问了ChatGPT:可以看到, 使用FunctionGraph只需要聚焦完成请求OpenAI接口的功能函数,不需要购买和配置资源,甚至不需要写Web接口的代码。 于是一个简单的方案如下:其中,对象存储服务OBS:用于托管前端页面FunctionGraph : 用于响应前端请求,运行代码向OpenAI发送问题API网关: 对外开放调用函数的API注:“函数” 是指客户部署在FunctionGraph上的代码,它可以是一个或多个文件组成的程序,甚至编译好的二进制文件。 如Python 脚本文件,Java的jar 包。三、开发并部署聊天应用3.1 创建FunctionGraph函数处理用户提问的请求首先创建并开发FunctionGraph函数,打开华为云FunctionGraph 产品页面,由于只有一个简单的问题查询接口,这里我们选用事件函数 使用Python 3.9 运行时。注:事件函数,可以由某类事件触发函数运行,如用户对该函数发送了HTTP请求,关联到该函数的消息队列里产生了新消息,都会自动触发函数运行。对于事件函数,通常程序入口方法(这里是 handler)会有两个参数:event 参数: 包含触发用户函数的事件的相关信息。HTTP请求也是一种事件,event里会包含请求的body header 等;context 参数: 调用平台的相关能力,如获取在函数配置里设置的加密环境变量等图:FunctionGraph 函数源码上图为本次调用的入口方法handler(),在函数中,我们:从event 里取得请求的参数 prompt调用OpenAI 的接口Python SDK,向OpenAI 发送请求, (示例里我们使用text-davinci-003模型 [1] https://platform.openai.com/docs/model-index-for-researchers#footnote-2)handler 方法中我们使用了 context 获取访问OpenAI的key(上图29行) ,获取前需要在函数上配置对应环境变量,如下图所示:图:函数配置环境变量注:示例中我们使用了OpenAI的sdk ,也可以将sdk放在函数代码里一起上传,或利用函数的依赖管理能力,通过添加依赖的方式实现:图:函数配置依赖在编辑好代码后,只需要点击部署按钮即可完成部署。3.2 创建APIG触发器来开放接口通常对于使用函数开发WEB 后端的场景,我们使用API 网关服务,来将函数开放出去供前端访问。为函数在API网关上注册API非常简单,只需要在函数页面上创建APIG触发器:注意:这里将后端超时时间设定为一个较大的时间,如60s,因为OpenAi的接口响应较慢。在北京4局点中,APIG服务有共享版,支持按需计费,若有较大的流量可以考虑购买APIG独享实例。图:为GPT函数绑定APIG触发器APIG触发器上的调用URL,可以直接用于向后端发送请求,该URL 为测试URL,每日仅可访问1000次,可以点击触发器跳转到APIG页面绑定自己的域名。3.3 托管前端页面到OBS我们准备了一个简单的前端,只需改下前端页面配置的后端地址即可。创建一个OBS 桶,上传前端文件配置OBS 桶静态文件托管,将桶访问权限设置为公共读,并在静态网站托管选项里配置默认首页,将自己的域名指向访问地址。最后,通过访问配置的域名访问页面,开始体验!至此,我们其实已经完成了整个简单聊天系统的搭建,案例中我们使用了一个简单的前端页面,开发者也可以考虑集成到如VSCode插件,语音聊天机器人,微信公众号等等。更进一步,若想使用Serverless技术,开发更为完整,适合生产环境的应用,需要添加鉴权,数据库连接等功能。 四、为后端服务增加接口鉴权以上我们已经基于FunctionGraph 函数创建了一个简易聊天系统的后端的服务,但是该接口没有任何鉴权,如果开放接口,所有用户都可以访问。如果需要用户登录后才可以使用,如何做?一个思路是在原有业务代码里增加鉴权,这里我们也可以考虑使用APIG自定义鉴权即APIG组合FunctionGraph 鉴权的形式。 一个新的解决方案,如下。4.1 创建并配置APIG自定义鉴权函数使用APIG 自定义鉴权有以下优势:提升开发效率:鉴权与业务解耦,新增逻辑只需关注业务,无需引入鉴权;鉴权代码集中而非分散在多个业务模块,更新鉴权逻辑只需要更新鉴权模块而非所有业务模块;降低成本:对于使用大规格函数进行后端服务的代码,无效请求可以直接由较小规格的鉴权函数拦截,降低大中规格资源服务的运行成本;创建鉴权函数和普通函数的创建流程一样,只需要注意响应的格式,一个使用JWT 鉴权的简单案例如下。 编辑接口,配置自定义鉴权编辑对应的API,选择自定义鉴权,选择到我们创建的函数:一个鉴权拒绝的示例如下:4.2 创建授权函数基于以上自定义鉴权模式,开发者可以组合自己已有的鉴权逻辑放到自定义鉴权函数中。如果进一步想基于FunctionGraph 创建一个 “登录” 或token授权函数,可以考虑以下方案。我们首先需要创建一个函数,该函数用于接收用户登录请求,然后去数据库请求,判断用户合法则返回鉴权token。创建授权函数创建一个普通的事件函数即可,一个简单的示例如下,随后可以为其创建APIG 触发器。 注意,如果需要函数访问VPC里的资源,如本例中的RDS,需要在函数页面配置RDS所在的VPC。五、“ChatGPT”的升级和“运维”5.1 日志与监控使用函数,系统会自动收集用户打印在控制台的日志,用户无需处理日志落盘,收集或直接上报。对于每一条请求日志,FunctionGraph 还会显示请求执行耗时,使用内存及请求状态。用户可以基于关键词,请求状态进行过滤和检索。 图:函数用户日志页面同时,平台自动收集函数运行指标,如调用次数,运行时间,错误次数,被拒绝次数,并发数等。图:函数监控5.2 版本迭代在用户更新函数代码时,为保障“ChatGPT”业务稳定运行,可以配置APIG触发器的后端服务指向函数别名:图:函数别名图:FunctionGraph别名灰度版本
  • [其他] 我真的傻了,
    我还真的去输入想要创作的第一个进去了,真的是无语