Flower既是一个反应式编程框架,又是一个分布式微服务框架。
Flower框架使得开发者无需关注反应式编程细节,即可得到一个反应式系统。
快速上手
Flower框架的主要元素包括:Flower Service(服务)、Flower 流程和Flow容器。Service实现一个细粒度的服务功能,Service之间通过Message关联,前一个Service的返回值(Message),必须是后一个Service的输入参数(Message),Service按照业务逻辑编辑成一个Flow(流程),Flower容器负责将前一个Service的返回消息,传递给后一个Service。
安装
Maven
Gradle
SBT
Ivy
Flower初始化
Flower使用前需要进行初始化,这里演示最简单的方式。
Flower初始化
定义Flower服务
开发Service类必须实现Flower框架的Service接口或者继承AbstractService基类,在process方法内完成服务业务逻辑处理。
UserServiceA
UserServiceB
UserServiceC1
服务注册
Flower提供两种服务注册方式:配置文件方式和编程方式。
服务流程编排
Flower框架提供两种服务流程编排方式:配置文件方式和编程方式。
两种编排方式的结果是一样:
调用Flower流程
前面定义了3个Flower服务,并编排了名称为flower_test的服务流程。那么怎么使用它呢?
完整示例
在Flower里面消息是一等公民,基于Flower开发的应用系统是面向消息的应用系统。 消息由Service产生,是Service的返回值;同时消息也是Service的输入。前一个Service的返回消息是下一个Service的输入消息,没有耦合的Service正是通过消息关联起来,组成一个Service流程,并最终构建出一个拥有完整处理能力的应用系统。流程举例:
术语
Flower消息处理模式
消息除了将服务串联起来,构成一个简单的串行流程,还可以组合应用,产生更强大的功能。
消息分叉
消息分叉是指,一个服务输出的消息,可能产生分叉,分发给1个或者多个其他服务。消息分叉后有两种处理方式,全部分发和条渗派瞎件分发。
全部分发
将输出消息分发给全部流程后续服务。后续多个服务接受到消息后,并行执行。这种模式多用于可并行执行的多个子任务,比如用户注册成功后,需丛空要1、将用户数据写入数据库,2、给用户发送激活邮件,3、给用户发送通知短信,4、将新用户注册信息发送给关联产品,实现账户打通。上述4个服务就可以采用消息全部分发模式,接受用户注册消息,并发完成上述4个任务。
要实现消息全部分发,需要在流程中进行配置,所有需要接受前序服务的输出消息的服务都要配置在流程中,如
service1是前序服务,service2和service3是后继服务。 如果service2和service3的class定义中,实现Service接口的声明中指定了泛型,则泛型类型必须是service1的输出类型或者其父类。
Service1
Service2
Service3
条件分发
有时候,前一个服务产生的消息,根据消息内容和业务逻辑可能会交给后续的某一个服务处理,而不是全部服务处理。比如用户贷款申请,当前服务计算出用户信用等级后,需要根据信用等级判断采用何种贷款方式,或者是拒绝贷款,不同贷款方式和拒绝贷款是不同的服务,这些服务在流程配置的时候,都需要配置为前序服务的后继服务,但是在运行期根据条件决定将消息分发给具体哪个后继服务。
实现条件分发在流程配置上和全部分发一样,所有可能的后继服务都要配置在流程中。具体实现条件分发有如下三种方式。
根据泛型进行分发
后续服务实现接口的时候声明不同的泛型类型,前序服务根据业务逻辑构建不同的消息类型,Flower会根据消息类型匹配对应的服务,只有成功匹配,消息才发送给过去。比如:
构建流程
声明ServiceB接受的消息类型为MessageB
ServiceA
ServiceB是ServiceA的后续服务,ServiceA收到的消息如果是字符串“b”,就会返回消息类型B,这时候框架就会将消息发送给ServiceB,而不会发送给ServiceC。
在消息中指定后继服务的id进行分发
前序消息实现Condition接口,并指定后继服务的id,如:
一般说来,服务是可复用的,可复用于不同的流程中,但是在不同的流程中后继服务可能是不同的,后继服务的id也是不同的,在服务中写死后续服务id,显然不利于服务的复用。解决方案有两种,一种是在不同的流程中,写一个专门用于分发的服务,也就是处理业务逻辑的服务并不关心消息的分发,只管返回消息内容,但是其后继服务是一个专门用来做消息分发的服务,这个服务没有业务逻辑,仅仅实现Condition接口根据消息内容指定后继服务。
另一种是使用框架内置服务ConditionService进行消息分发
使用框架内置服务ConditionService进行消息分发
ConditionService是一个通用的消息分发服务,
服务serviceE要将消息根据条件分发给serviceF或者serviceG,流程配置如上,中间加入serviceCondition进行适配。 serviceCondition的服务注册方法为
com.ly.train.flower.common.service.ConditionService为框架内置服务
这种方式中,依然需要在serviceCondition的前驱服务serviceE中设置返回消息的condition,但是不必设置后续服务的id,只需要设置后续服务的顺序号即可。
几种条件分发的代码示例参考/flower.sample/src/main/java/com/ly/train/flower/common/sample/condition/Sample.java
消息聚合
对于全部分发的消息分叉而言,通常目的在于使多个服务能够并行执行,加快处理速度。通常还需要得到这些并行处理的服务的全部结果,进行后续处理。 在Flower中,得到多个并行处理服务的结果消息,称为消息聚合。实现方式为,在流程中,配置需要聚合的多个消息的后续服务为com.ly.train.flower.common.service.AggregateService,这是一个框架内置服务,负责聚合多个并行服务产生的消息,将其封装到一个Set对象中返回。 如流程
这里的service5就是一个消息聚合服务,负责聚合并行的service2和service3产生的消息,并把聚合后的Set消息发送给service4. 服务配置如下,service5配置为框架内置服务AggregateService。
service4负责接收处理聚合后的消息,从Set中取出各个消息,分别处理。
消息回复
Flower中的消息全部都是异步处理,也就是服务之间不会互相阻塞等待,以实现低耦合、无阻塞、高并发的响应式系统。Flower流程调用者发送出请求消息以后,消息在流程中处理,调用者无需阻塞等待处理结果,可以继续去执行其他的计算任务。
和传统的命令式编程不同,通常流程的发起调用者并不是流程处理结果的最终接受者,比如对于web开发,流程的发起者通常是一个servlet,但是真正接受处理结果的是用户端浏览器或者App,流程中的服务可以直接发送处理结果给用户端,而不必通过servlet。也就是调用发起者servlet无需等待流程服务的最终处理结果,将用户请求发送到流程中后,不必阻塞等待处理,可以立即获取另一个用户的请求继续进行处理。
但是Flower也支持调用者阻塞等待消息处理结果,消息回复模式可以使流程调用者得到流程处理的最终结果消息。可参考代码示例 /flower.sample/src/main/java/com/ly/train/flower/common/sample/textflow/Sample.java
Flower web开发模式
Flower集成Servlet3的web开发模式
Flower支持Servlet3的异步模式,请求处理线程在调用Flower流程,并传入AsyncContext对象后立即释放。 代码示例参考/flower.sample/src/main/java/com/ly/train/flower/common/sample/web/async/AsyncServlet.java
开发支持Servlet3的Flower服务,需要实现框架的Service接口,在方法 Object process(T message, ServiceContext context) throws Exception中,Flower框架会传入一个Web对象,通过context.getWeb()得到Web对象,用以获得请求参数和输出处理响应结果。
Flower集成Spring boot的web开发模式
Flower支持Spring boot开发,在项目中依赖flower.web,实现框架中的Service接口和InitController接口。 初始化@BindController注解需要的参数,在编译过程中自动由flower.web枚举@BindController注解, 生成Spring boot需要的Controller。
注意: flower.web利用annotation为Service生成spring boot所需的Controller类。这个生成过程在程序编译的时候完成,如果IDE环境不支持热编译,需要在命令行执行mvn install生成代码。
代码示例参考/flower.sample/src/main/java/com/ly/train/flower/common/sample/springboot
使用Flower框架的开发建议
Flower分布式部署架构
开发流程
一. 启动Flower.center注册中心
二. 开发Flower Service,启动业务服务Flower容器,自动向注册中心注册服务
三. 开发Flower web网关,启动Flower网关服务,编排流程
一. 注册中心
Flower.center基于spring-boot开发,通过打包成fat-jar后通过命令行启动即可。
Flower注册中心启动入口/flower.center/src/main/java/com/ly/train/flower/center/CenterApplication.java Flower注册中心启动命令java -jar flower.center-0.1.2.jar
二. 启动业务Flower容器
Flower部署支持Flower容器和Spring容器,下面的例子基于spring-boot演示
2.1 创建配置文件flower.yml
2.2 配置FlowerFactory
2.3 开发flower服务
2.4 创建启动类
三. 启动网关服务器,编排流程
3.1 创建flower.yml
3.2 配置FlowerFactory
3.3 开发Flower服务
3.4 开发网关Controller
3.5 启动类
实例项目细节
flower分布式实例 https://github.com/leeyazhou/flower.showcase.git
核心概念
FlowerFactory
使用默认的FlowerFactory
按需创建自己的FlowerFactory,配置文件路径默认读取classpath:flower.yml,配置文件内容格式为yaml风格,详情查看配置信息。
获取FlowerFactory之后,就可以使用它提供的接口:
FlowRouter流程路由器,创建流程之后,通过FlowerFactory可以创建出对应的路由器,之后便可以进行服务的调用了。
分布式
Flower.yml配置信息
了解关于Flower的内部设计,有助于你更好地利用Flower开发一个反应式系统。
Flower core模块(进程内流式微服务框架)设计
Flower基于Akka的Actor进行开发,将Service封装到Actor里面,Actor收到的消息作为参数传入Service进行调用,Service的输出发送给后续Actor作为Service的输入。
Flower核心类
Flower初始化及调用时序
服务流程初始化
消息流处理
Flower的核心设计不过如此。但是由此延伸出来的应用方法和设计模式却和Akka有了极大的不同。
分布式流式微服务框架设计
传统的分布式微服务框架通过远程调用的方式实现服务的解耦与分布式部署,使得系统开发、维护、服务复用、集群部署更加方便灵活,但是这种微服务依然许多不足之处
流式微服务框架Flower致力于构建一种新的微服务架构体系,使用流式计算的架构思想,以一种更加轻量、更易于设计开发、消息驱动、弱依赖,异步并发的技术特点开发实现微服务系统
架构
部署模型
Flower将整个应用系统集群统一管理控制,控制中心控制管理集群的所有资源
Agent部署在集群每一台服务器上,负责加载服务实例,并向控制中心汇报状态
代码仓库负责管理服务的java程序包,程序包用assembly打包
控制中心和Agent基于Akka开发,每个服务包装一个actor里面,actor之间负责消息的通信
集群启动与服务部署时序模型
注册服务数据结构
服务之间的依赖关系在控制中心编排
class HappyActor extends Actor{public void act(){print("HappyActor")}
}
class SadActor extends Actor{
public void atc(){print("SadActor"饥消手)}
}
print("HappyActor")
是什么意思?打印吗?
但你没有关于打印方法。
如果是想打印"HappyActor"(没有桥贺调用其它方法的情况下)
应该是这样烂嫌System.out.print("HappyActor")
而且在actor中没有act
系统用户业务主角和涉众隐橡历三者的关系?答:主角又称参与者,官方定义是:在系统之外与系统交互的人或事。所以要找到参与者,首先要分清楚系统的边界,即系统之外是哪里。可以通过两个问题来找到这个边界:1、 谁对系统有着明确的目标和要求并且主动发出动作(系统外部)?
2、系统是为谁服务的(系统内部)?
主角不一定是人,可以是发出启动一个用例动作的任何事物,如计算机系统,计时器,传感器等...
主角与涉众的关系:涉众是与要建设的这个系统有利益相关的一切人和事,主角是涉众代表。
主角与用户关系:用户是系统的使用者,是主角的实例。
主角与角色的关系:角色是主角的职责,角色是将众多参与者职责中抽象出相同的那一部分,将其命名而形成一个角色。角色一般适用于概念阶段的模型里面,以表达业务的逻辑理解。
打开CSDN APP,看更多技术内容
UML(thinking in uml 学习)--参与者和业务工人和涉众
占位 哈哈哈哈
继续访问
【数据库系统】第三讲 关系模型的基本概念
3.1 关系模型概述 1、关系模型的提出 2、关系模型的研究内容 一个关系就是一个Table 关系模型就是处理Table的,由三部分组成: 描述DB各种数据的基本结构形式(Table/Relation) 描述Table与Table之间所可能发生的各种 *** 作(关系运算) 描述这些 *** 作所应遵循的约束条件(完整性约束) 简单的说,即Table如何描述,有哪些 *** 作、结果是什么、有哪些约束等 3、关系模型...
继续访问
Actor模型学习
最近看到了一篇写的贼好的blog,讲的完全详细,看得出来笔者的功力,所以赶紧转载过来,最下面有原文的地址。 大家一起共勉! 传统的游戏服务器要么是单线程要么是多线程,过去几十年里CPU一直遵循摩尔定律发展,带来的结果是单核频率越来越高。而近几年摩尔定义在CPU上已然失效,为什么呢? 大于在2003年左右,计算机的核心特性经历了一个重要的变化,处理器的速度达到了一个顶点。在接下来近15年里,时钟...
继续访问
Actor模型概念
转载自:https://blog.csdn.net/u014659211/article/details/63686965 从实习到现在,一直在做Unity相关的业务,不知不觉中感觉已经不在关注服务器相关的技术了。一次偶然的机会再腾讯的gad平台上观看了云风在15年在腾讯做的skynet讲座(http://gad.qq.com/content/coursedetail/467),skynet是用...
继续访问
深入解析actor 模型(一): actor 介绍及在游戏行业应用
1 介绍 1.1 什灶搜么是actor 对于刚接触actor的我,第一感觉就像redis一样,每个actor就是一个redis 实例,都有自己消息队列,actor相互通信通过将消息发给对方,消息发送如旁进对方的消息队列,等待对方线程处理。来看看我们之前做项目的痛点。 游戏服务器通常分为多个服,每个服上有多个玩家。假设玩家与玩家数据交互 *** 作,这时怎么避免数据竞争?两种解决方案: 1、将数据写入redis 首先redis效率高,也是单线程模型,不存在数据竞争,但是也有它的不足之处, *** 作redis 会受网络影响
继续访问
java actor akka_如何使用Akka actor处理Java期货
我在Java Web应用程序中有一个分层架构. UI层只是Java,服务是类型化的Akka actor,外部服务调用(WS,DB等)包含在Hystrix命令中.UI调用服务,服务返回Akka未来.这是Akka的未来,因为我希望使用Akka期货提供的onComplete和onFailure回调来简化UI编码.然后,该服务创建执行某些映射等的未来,并将调用包装回返回Java未来的HystrixComm...
继续访问
Actor模型
传统的游戏服务器要么是单线程要么是多线程,过去几十年里CPU一直遵循摩尔定律发展,带来的结果是单核频率越来越高。而近几年摩尔定义在CPU上已然失效,为什么呢? 大于在2003年左右,计算机的核心特性经历了一个重要的变化,处理器的速度达到了一个顶点。在接下来近15年里,时钟速度是呈线性增长的,而不会像以前那样以指数级的速度增长。 由于CPU的工艺制程和发热稳定性之间难以取舍,取而代之...
继续访问
actor-kotlin
actor-kotlin Java动态伪装工具,能够用伪装接口代理真实对象。(The Java dynamic camouflage tool can use the camouflage interface to proxy real objects.) 纯Kotlin开发,使用简单但功能强大,可用于组件化开发或插件化项目开发。 Android Demo: https://github.com/xuehuiniaoyu/actor-demo implementation 'io.github.xuehui
继续访问
天天酷跑多态
package Tianpublic class Actor{ String namePet petpackage Tianpublic final class Bear extends Pet { public void run(){ System.out.println("我是雄二,我喜欢蜂蜜")} } ...
继续访问
并发模型值Actor和CSP
CSP的是(CSP)的缩写,翻译成中文是顺序通信进程,简称CSP的核心思想是多个线程之间通过Channel来通信,对应到golang中的chan结构,对应到Python中是QueueGo语言的CSP模型是由协程Goroutine与通道ChannelGo协程goroutine是一种轻量线程,它不是 *** 作系统的线程,而是将一个 *** 作系统线程分段使用,通过调度器实现协作式调度。是一种绿色线程,微线程,它与Coroutine协程也有区别,能够在发现堵塞后启动新的微线程。通道channel类似Unix的Pipe。....
继续访问
Actor模型和CSP模型的区别
Akka/Erlang的actor模型与Go语言的协程Goroutine与通道Channel代表的CSP(Communicating Sequential Processes)模型有什么区别呢? 首先这两者都是并发模型的解决方案,我们看看Actor和Channel这两个方案的不同: Actor模型 在Actor模型中,主角是Actor,类似一种worker,Actor彼此之间直接...
继续访问
Actor模式初步入门
Actor模型概念 Actor模型为并行而生,简单说是未解决高并发的一种编程思路。在Actor模型中,主角是Actor,类似一种worker,Actor彼此之间直接发送消息,不需要经过什么中介,消息是异步发送和处理的。在Actor模式中,“一切皆是Actor”,所有逻辑或者模块均别看做Actor,通过不同Actor之间的消息传递实现模块之间的通信和交互。Actor模型描述了一...
继续访问
并行编程模型之Actor/CSP/PGAS
并行编程模型之Actor/CSP/PGASActor1.背景2. 简介3.actor组成ActorMailbox邮箱behavior行为4.优势无锁异步隔离容错分布式5.劣势6.实践素数计算CSP1.简介2.CSP与go语言2.1 组成2.2Goroutine调度器3.Actor模型和CSP模型的区别PGAS1.简介2.实现 Actor 1.背景 处理并发问题就是如何保证共享数据的一致性和正确性,一般来说有两种策略用来在并发线程中进行通信:共享数据和消息传递。 熟悉c和java并发编程的都会比较熟悉
继续访问
go Actor模型和CSP模型的区别
Actor模型和CSP模型的区别 Akka/Erlang的actor模型与Go语言的协程Goroutine与通道Channel代表的CSP(Communicating Sequential Processes)模型有什么区别呢? 首先这两者都是并发模型的解决方案,我们看看Actor和Channel这两个方案的不同: Actor模型 在Actor模型中,主角是Actor,类似一种worker,Actor彼此之间直接发送消息,不需要经过什么中介,消息是异步发送和处理的 Actor.
继续访问
控制`Actor`朝向,运动 Learn Unreal Engine (with C++)
控制`Actor`的朝向,以及
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)