响应式微服务框架Flower——快速上手

摘要:
快速上手Flower框架的主要元素包括:FlowerService(服务)、Flower流程和Flow容器。系统要求Flower要求Java8作为基础。$java-version安装Flower当前最新发布版本是1.0.3。Flower初始化FlowerFactoryflowerFactory=newSimpleFlowerFactory();定义Flower服务开发Service类必须实现Flower框架的Service接口或者继承AbstractService基类,在process方法内完成服务业务逻辑处理。编程方式ServiceFactoryserviceFactory=flowerFactory.getServiceFactory();serviceFactory.registerService;serviceFactory.registerService;serviceFactory.registerService;配置文件方式服务定义配置文件扩展名:.services,放在classpath下,Flower框架自动加载注册。
快速上手

Flower框架的主要元素包括:Flower Service(服务)、Flower 流程和Flow容器。Service实现一个细粒度的服务功能,Service之间通过Message关联,前一个Service的返回值(Message),必须是后一个Service的输入参数(Message),Service按照业务逻辑编辑成一个Flow(流程),Flower容器负责将前一个Service的返回消息,传递给后一个Service。

系统要求

Flower要求Java 8作为基础。如果使用servlet开发,最低要求是servlet 3.1+,才能支持异步请求。在开始前,最好确认当前安装的JDK版本号是否符合要求。

$ java -version

安装

Flower当前最新发布版本是1.0.3。

Maven

<dependency>
  <groupId>com.ly.train</groupId>
  <artifactId>flower.core</artifactId>
  <version>A.B.C</version>
</dependency>

Gradle

compile group: 'com.ly.train', name: 'flower.core', version: 'A.B.C'

SBT

libraryDependencies += "com.ly.train" % "flower.core" % "A.B.C"

Ivy

<dependency org="com.ly.train" name="flower.core" rev="A.B.C"/>

Flower初始化

Flower使用前需要进行初始化,这里演示最简单的方式。

Flower初始化

 FlowerFactory flowerFactory = new SimpleFlowerFactory();

定义Flower服务

开发Service类必须实现Flower框架的Service接口或者继承AbstractService基类,在process方法内完成服务业务逻辑处理。

UserServiceA

public class UserServiceA implements Service<User, User> {
  static final Logger logger = LoggerFactory.getLogger(UserServiceA.class);
  @Override
  public User process(User message, ServiceContext context) throws Throwable {
    message.setDesc(message.getDesc() + " --> " + getClass().getSimpleName());
    message.setAge(message.getAge() + 1);
    logger.info("结束处理消息, message : {}", message);
    return message;
  }

}

UserServiceB

public class UserServiceB implements Service<User, User> {
  static final Logger logger = LoggerFactory.getLogger(UserServiceB.class);
  @Override
  public User process(User message, ServiceContext context) throws Throwable {
    message.setDesc(message.getDesc() + " --> " + getClass().getSimpleName());
    message.setAge(message.getAge() + 1);
    logger.info("结束处理消息, message : {}", message);
    return message;
  }

}

UserServiceC1

public class UserServiceC1 implements Service<User, User> {
  static final Logger logger = LoggerFactory.getLogger(UserServiceC1.class);
  @Override
  public User process(User message, ServiceContext context) throws Throwable {
    message.setDesc(message.getDesc() + " --> " + getClass().getSimpleName());
    message.setAge(message.getAge() + 1);
    logger.info("结束处理消息, message : {}", message);
    return message;
  }

}

服务注册

Flower提供两种服务注册方式:配置文件方式和编程方式。

编程方式

 ServiceFactory serviceFactory = flowerFactory.getServiceFactory();
 serviceFactory.registerService(UserServiceA.class.getSimpleName(), UserServiceA.class);
 serviceFactory.registerService(UserServiceB.class.getSimpleName(), UserServiceB.class);
 serviceFactory.registerService(UserServiceC1.class.getSimpleName(), UserServiceC1.class);

配置文件方式

服务定义配置文件扩展名: .services,放在classpath下,Flower框架自动加载注册。
flower_test.services

UserServiceA = com.ly.train.flower.base.service.user.UserServiceA
UserServiceB = com.ly.train.flower.base.service.user.UserServiceB
UserServiceC1 = com.ly.train.flower.base.service.user.UserServiceC1

服务流程编排

Flower框架提供两种服务流程编排方式:配置文件方式和编程方式。

两种编排方式的结果是一样:

UserServiceA -> UserServiceB -> UserServiceC1

编程方式编排流程

// UserServiceA -> UserServiceB -> UserServiceC1
final String flowName = "flower_test";
ServiceFlow serviceFlow = serviceFactory.getOrCreateServiceFlow(flowName);
serviceFlow.buildFlow(UserServiceA.class, UserServiceB.class);
serviceFlow.buildFlow(UserServiceB.class, UserServiceC1.class);
serviceFlow.build();

配置文件方式编排流程

流程配置文件扩展名: .flow,放在classpath下,Flower框架自动加载编排流程。
flower_test.flow

UserServiceA -> UserServiceB
UserServiceB -> UserServiceC1

调用Flower流程

前面定义了3个Flower服务,并编排了名称为flower_test的服务流程。那么怎么使用它呢?

  1. 同步调用,需要Flower服务流程响应结果。
  2. 异步调用,不需要Flower服务流程响应结果。
  • 同步调用
final FlowRouter flowRouter = flowerFactory.buildFlowRouter(flowName, 16);
Object result = flowRouter.syncCallService(user);
  • 异步调用
final FlowRouter flowRouter = flowerFactory.buildFlowRouter(flowName, 16);
flowRouter.asyncCallService(user);

完整示例

    FlowerFactory flowerFactory = new SimpleFlowerFactory();
    ServiceFactory serviceFactory = flowerFactory.getServiceFactory();
    serviceFactory.registerService(UserServiceA.class.getSimpleName(), UserServiceA.class);
    serviceFactory.registerService(UserServiceB.class.getSimpleName(), UserServiceB.class);
    serviceFactory.registerService(UserServiceC1.class.getSimpleName(), UserServiceC1.class);

    final String flowName = "flower_test";
    ServiceFlow serviceFlow = serviceFactory.getOrCreateServiceFlow(flowName);
    serviceFlow.buildFlow(UserServiceA.class, UserServiceB.class);
    serviceFlow.buildFlow(UserServiceB.class, UserServiceC1.class);
    serviceFlow.build();

    final FlowRouter flowRouter = flowerFactory.buildFlowRouter(flowName, 16);

    User user = new User();
    user.setName("响应式编程 ");
    user.setAge(2);

    Object o = flowRouter.syncCallService(user);
    System.out.println("响应结果: " + o);

    flowRouter.asyncCallService(user);

运行结果

2019-07-11 15:13:19.739 [main] INFO  c.ly.train.flower.config.parser.FlowerConfigParser - parse FlowerConfig, configLocation : flower.yml
2019-07-11 15:13:19.839 [main] INFO  c.ly.train.flower.config.parser.FlowerConfigParser - flowerConfig : FlowerConfig [name=LocalFlower, host=127.0.0.1, port=25005, basePackage=com.ly.train.flower, registry=null]
2019-07-11 15:13:19.840 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : com.ly.train.flower.core.service.container.simple.SimpleFlowerFactory@39aeed2f
2019-07-11 15:13:19.844 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : com.ly.train.flower.core.service.container.ServiceFactory@724af044
2019-07-11 15:13:19.844 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : com.ly.train.flower.core.service.container.ServiceLoader@4678c730
2019-07-11 15:13:19.957 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - find service, path : file:/Volumes/Data/opt/code/yilong/flower/flower.core/target/test-classes/sample.services
2019-07-11 15:13:19.966 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. service1 : ServiceMeta [serviceName=service1, paramType=com.ly.train.flower.base.model.User, resultType=com.ly.train.flower.base.model.User, serviceClassName=com.ly.train.flower.base.service.user.UserServiceA, configs=[]]
2019-07-11 15:13:19.966 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> service1 : class com.ly.train.flower.base.service.user.UserServiceA
2019-07-11 15:13:19.967 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. service2 : ServiceMeta [serviceName=service2, paramType=com.ly.train.flower.base.model.User, resultType=com.ly.train.flower.base.model.User, serviceClassName=com.ly.train.flower.base.service.user.UserServiceB, configs=[]]
2019-07-11 15:13:19.967 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> service2 : class com.ly.train.flower.base.service.user.UserServiceB
2019-07-11 15:13:19.968 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. service3 : ServiceMeta [serviceName=service3, paramType=com.ly.train.flower.base.model.User, resultType=com.ly.train.flower.base.model.User, serviceClassName=com.ly.train.flower.base.service.user.UserServiceC1, configs=[]]
2019-07-11 15:13:19.968 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> service3 : class com.ly.train.flower.base.service.user.UserServiceC1
2019-07-11 15:13:20.017 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.core/target/test-classes/com/ly/train/flower
2019-07-11 15:13:20.059 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - add class:com.ly.train.flower.base.service.OpenTracerService
2019-07-11 15:13:20.061 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - add class:com.ly.train.flower.base.service.user.UserServiceD
2019-07-11 15:13:20.062 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - add class:com.ly.train.flower.base.service.str.StringServiceD
2019-07-11 15:13:20.062 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.core/target/classes/com/ly/train/flower
2019-07-11 15:13:20.123 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.common/target/classes/com/ly/train/flower
2019-07-11 15:13:20.156 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.config/target/classes/com/ly/train/flower
2019-07-11 15:13:20.157 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.filter/flower.filter.api/target/classes/com/ly/train/flower
2019-07-11 15:13:20.160 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.registry/flower.registry.api/target/classes/com/ly/train/flower
2019-07-11 15:13:20.164 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.serializer/flower.serializer.hessian/target/classes/com/ly/train/flower
2019-07-11 15:13:20.166 [main] DEBUG c.l.t.f.common.scanner.filter.AbstractClassFilter - scan url : file:/Volumes/Data/opt/code/yilong/flower/flower.serializer/flower.serializer.api/target/classes/com/ly/train/flower
2019-07-11 15:13:20.167 [main] INFO  c.l.t.flower.core.service.container.ServiceFactory - scan flowerService, basePackage : com.ly.train.flower, find flowerService : 3
2019-07-11 15:13:20.168 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. UserServiceD : ServiceMeta [serviceName=UserServiceD, paramType=java.util.List, resultType=java.util.List, serviceClassName=com.ly.train.flower.base.service.user.UserServiceD, configs=[]]
2019-07-11 15:13:20.168 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> UserServiceD : class com.ly.train.flower.base.service.user.UserServiceD
2019-07-11 15:13:20.168 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. OpenTracerService : ServiceMeta [serviceName=OpenTracerService, paramType=com.ly.train.flower.base.model.User, resultType=com.ly.train.flower.base.model.User, serviceClassName=com.ly.train.flower.base.service.OpenTracerService, configs=[]]
2019-07-11 15:13:20.168 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> OpenTracerService : class com.ly.train.flower.base.service.OpenTracerService
2019-07-11 15:13:20.168 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. StringServiceD : ServiceMeta [serviceName=StringServiceD, paramType=java.util.List, resultType=java.util.List, serviceClassName=com.ly.train.flower.base.service.str.StringServiceD, configs=[]]
2019-07-11 15:13:20.168 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> StringServiceD : class com.ly.train.flower.base.service.str.StringServiceD
2019-07-11 15:13:20.661 [main] INFO  com.ly.train.flower.core.akka.FlowerActorSystem - akka config :akka.actor.provider = "remote"
akka.remote.enabled-transports = ["akka.remote.netty.tcp"]
akka.remote.netty.tcp.hostname = "127.0.0.1"
akka.remote.netty.tcp.port = "25005"
dispatcher.fork-join-executor.parallelism-min = "8"
dispatcher.fork-join-executor.parallelism-max = "256"
dispatcher.fork-join-executor.parallelism-factor = "8"

2019-07-11 15:13:21.378 [flower-dispatcher-4] INFO  akka.event.slf4j.Slf4jLogger - Slf4jLogger started
2019-07-11 15:13:21.411 [flower-dispatcher-4] INFO  akka.remote.Remoting - Starting remoting
2019-07-11 15:13:21.622 [flower-dispatcher-4] INFO  akka.remote.Remoting - Remoting started; listening on addresses :[akka.tcp://flower@127.0.0.1:25005]
2019-07-11 15:13:21.624 [flower-dispatcher-4] INFO  akka.remote.Remoting - Remoting now listens on addresses: [akka.tcp://flower@127.0.0.1:25005]
2019-07-11 15:13:21.677 [main] INFO  com.ly.train.flower.common.util.ExtensionLoader - url : file:/Volumes/Data/opt/code/yilong/flower/flower.serializer/flower.serializer.hessian/target/classes/META-INF/services/flower/com.ly.train.flower.serializer.Serializer
2019-07-11 15:13:21.677 [main] INFO  com.ly.train.flower.common.util.ExtensionLoader - url : file:/Volumes/Data/opt/code/yilong/flower/flower.serializer/flower.serializer.api/target/classes/META-INF/services/flower/com.ly.train.flower.serializer.Serializer
2019-07-11 15:13:21.705 [main] INFO  com.ly.train.flower.common.util.ExtensionLoader - load extend(hessian) : class com.ly.train.flower.serializer.hessian.HessianSerializer
2019-07-11 15:13:21.775 [flower-dispatcher-4] WARN  akka.serialization.Serialization(akka://flower) - Using serializer [com.ly.train.flower.core.akka.serializer.hessian.HessianSerializer] for message [akka.actor.ActorSelectionMessage]. Note that this serializer is not implemented by Akka. It's not recommended to replace serializers for messages provided by Akka.
2019-07-11 15:13:21.787 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : com.ly.train.flower.core.akka.ServiceActorFactory@7f132176
2019-07-11 15:13:21.788 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : com.ly.train.flower.core.akka.FlowerActorSystem@68b32e3e
2019-07-11 15:13:21.788 [main] INFO  c.l.t.f.c.s.container.simple.SimpleFlowerFactory - start FlowerFactory
2019-07-11 15:13:21.788 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. UserServiceA : ServiceMeta [serviceName=UserServiceA, paramType=com.ly.train.flower.base.model.User, resultType=com.ly.train.flower.base.model.User, serviceClassName=com.ly.train.flower.base.service.user.UserServiceA, configs=[]]
2019-07-11 15:13:21.788 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> UserServiceA : class com.ly.train.flower.base.service.user.UserServiceA
2019-07-11 15:13:21.788 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. UserServiceB : ServiceMeta [serviceName=UserServiceB, paramType=com.ly.train.flower.base.model.User, resultType=com.ly.train.flower.base.model.User, serviceClassName=com.ly.train.flower.base.service.user.UserServiceB, configs=[]]
2019-07-11 15:13:21.788 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> UserServiceB : class com.ly.train.flower.base.service.user.UserServiceB
2019-07-11 15:13:21.789 [main] DEBUG c.l.t.flower.core.service.container.ServiceLoader - init ServiceMeta. UserServiceC1 : ServiceMeta [serviceName=UserServiceC1, paramType=com.ly.train.flower.base.model.User, resultType=com.ly.train.flower.base.model.User, serviceClassName=com.ly.train.flower.base.service.user.UserServiceC1, configs=[]]
2019-07-11 15:13:21.789 [main] INFO  c.l.t.flower.core.service.container.ServiceLoader - register service type -> UserServiceC1 : class com.ly.train.flower.base.service.user.UserServiceC1
2019-07-11 15:13:21.790 [main] INFO  c.l.t.flower.core.service.container.ServiceFlow -  buildFlow : flower_test, preService : UserServiceA, nextService : UserServiceB
2019-07-11 15:13:21.790 [main] INFO  c.l.t.flower.core.service.container.ServiceFlow -  buildFlow : flower_test, preService : UserServiceB, nextService : UserServiceC1
2019-07-11 15:13:21.790 [main] INFO  c.l.t.flower.core.service.container.ServiceFlow -  build flower_test success.
 ServiceFlow [ flowName = flower_test
  UserServiceA(1) ---> UserServiceB(1),
  UserServiceB(1) ---> UserServiceC1(0)
]
2019-07-11 15:13:21.790 [main] INFO  c.l.t.flower.core.service.container.ServiceFlow - start register ServiceConfig : ServiceConfig [flowName=flower_test, serviceName=UserServiceA, jointSourceNumber=0]
2019-07-11 15:13:21.790 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : com.ly.train.flower.core.akka.router.FlowRouter@bcef303
2019-07-11 15:13:21.790 [main] INFO  com.ly.train.flower.common.util.ExtensionLoader - url : file:/Volumes/Data/opt/code/yilong/flower/flower.core/target/classes/META-INF/services/flower/com.ly.train.flower.core.loadbalance.LoadBalance
2019-07-11 15:13:21.791 [main] INFO  com.ly.train.flower.common.util.ExtensionLoader - load extend(round) : class com.ly.train.flower.core.loadbalance.RoundLoadBalance
2019-07-11 15:13:21.791 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : ServiceRouter [loadBalance=RoundLoadBalance [name=RoundLoadBalance], number=1, serviceConfig=ServiceConfig [flowName=flower_test, serviceName=UserServiceA, jointSourceNumber=0]]
2019-07-11 15:13:21.792 [main] INFO  com.ly.train.flower.core.akka.ServiceActorFactory - build service Router. serviceName : UserServiceA, actorNumber : 1
2019-07-11 15:13:21.793 [main] INFO  com.ly.train.flower.core.akka.ServiceActorFactory - build service Router. flowName : flower_test, serviceName : UserServiceA, flowNumber : 1
2019-07-11 15:13:21.928 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : com.ly.train.flower.core.akka.router.FlowRouter@5ef6ae06
2019-07-11 15:13:21.928 [main] DEBUG com.ly.train.flower.common.lifecyle.AbstractInit - init class : ServiceRouter [loadBalance=RoundLoadBalance [name=RoundLoadBalance], number=16, serviceConfig=ServiceConfig [flowName=flower_test, serviceName=UserServiceA, jointSourceNumber=0]]
2019-07-11 15:13:21.935 [main] INFO  com.ly.train.flower.core.akka.ServiceActorFactory - build service Router. serviceName : UserServiceA, actorNumber : 16
2019-07-11 15:13:21.936 [main] INFO  com.ly.train.flower.core.akka.ServiceActorFactory - build service Router. flowName : flower_test, serviceName : UserServiceA, flowNumber : 16
2019-07-11 15:13:21.953 [flower-dispatcher-20] INFO  c.l.t.flower.core.service.container.ServiceLoader - load flower service --> UserServiceA : com.ly.train.flower.base.service.user.UserServiceA@55967dc0
2019-07-11 15:13:21.958 [flower-dispatcher-20] INFO  com.ly.train.flower.base.service.user.UserServiceA - 结束处理消息, message : User [name=响应式编程 , desc= --> UserServiceA, age=3]
2019-07-11 15:13:21.961 [flower-dispatcher-20] DEBUG c.l.t.f.core.akka.actor.wrapper.ActorRefWrapper - Local message. serviceName : UserServiceB, actor : Actor[akka://flower/user/flower/UserServiceB_1#-39642247], message : ServiceContext [id=b66cc2e27fea491593b9e862e1b311a6, flowName=flower_test, currentServiceName=UserServiceB, sync=true, attachments=null, flowMessage=FlowMessage [transactionId=6e440adf3f8c41f793d7c700a4a36deb, message=[B@611ed8fb], web=null], sender : Actor[akka://flower/user/flower/UserServiceA_1#518152440]
2019-07-11 15:13:21.963 [flower-dispatcher-19] INFO  c.l.t.flower.core.service.container.ServiceLoader - load flower service --> UserServiceB : com.ly.train.flower.base.service.user.UserServiceB@ffcaad2
2019-07-11 15:13:21.963 [flower-dispatcher-19] INFO  com.ly.train.flower.base.service.user.UserServiceB - 结束处理消息, message : User [name=响应式编程 , desc= --> UserServiceA --> UserServiceB, age=4]
2019-07-11 15:13:21.964 [flower-dispatcher-19] DEBUG c.l.t.f.core.akka.actor.wrapper.ActorRefWrapper - Local message. serviceName : UserServiceC1, actor : Actor[akka://flower/user/flower/UserServiceC1_1#-1935204307], message : ServiceContext [id=b66cc2e27fea491593b9e862e1b311a6, flowName=flower_test, currentServiceName=UserServiceC1, sync=true, attachments=null, flowMessage=FlowMessage [transactionId=6e440adf3f8c41f793d7c700a4a36deb, message=[B@40065f66], web=null], sender : Actor[akka://flower/user/flower/UserServiceB_1#-39642247]
2019-07-11 15:13:21.964 [flower-dispatcher-19] INFO  c.l.t.flower.core.service.container.ServiceLoader - load flower service --> UserServiceC1 : com.ly.train.flower.base.service.user.UserServiceC1@2a46d78e
2019-07-11 15:13:21.964 [flower-dispatcher-19] INFO  c.ly.train.flower.base.service.user.UserServiceC1 - 结束处理消息, message : User [name=响应式编程 , desc= --> UserServiceA --> UserServiceB --> UserServiceC1, age=5]
响应结果: User [name=响应式编程 , desc= --> UserServiceA --> UserServiceB --> UserServiceC1, age=5]
2019-07-11 15:13:21.965 [main] DEBUG c.l.t.f.core.akka.actor.wrapper.ActorRefWrapper - Local message. serviceName : UserServiceA, actor : Actor[akka://flower/user/flower/UserServiceA_2#1690671066], message : ServiceContext [id=2e6fcef3852a48eeb7cb182d2bd62ef4, flowName=flower_test, currentServiceName=UserServiceA, sync=false, attachments=null, flowMessage=FlowMessage [transactionId=52565043086d49abaa2ca88c3527883e, message=[B@54dcfa5a], web=null], sender : null
2019-07-11 15:13:21.966 [flower-dispatcher-19] INFO  com.ly.train.flower.base.service.user.UserServiceA - 结束处理消息, message : User [name=响应式编程 , desc= --> UserServiceA, age=3]
2019-07-11 15:13:21.967 [flower-dispatcher-19] DEBUG c.l.t.f.core.akka.actor.wrapper.ActorRefWrapper - Local message. serviceName : UserServiceB, actor : Actor[akka://flower/user/flower/UserServiceB_2#1505663876], message : ServiceContext [id=2e6fcef3852a48eeb7cb182d2bd62ef4, flowName=flower_test, currentServiceName=UserServiceB, sync=false, attachments=null, flowMessage=FlowMessage [transactionId=52565043086d49abaa2ca88c3527883e, message=[B@3ccff905], web=null], sender : Actor[akka://flower/user/flower/UserServiceA_2#1690671066]
2019-07-11 15:13:21.967 [flower-dispatcher-20] INFO  com.ly.train.flower.base.service.user.UserServiceB - 结束处理消息, message : User [name=响应式编程 , desc= --> UserServiceA --> UserServiceB, age=4]
2019-07-11 15:13:21.968 [flower-dispatcher-20] DEBUG c.l.t.f.core.akka.actor.wrapper.ActorRefWrapper - Local message. serviceName : UserServiceC1, actor : Actor[akka://flower/user/flower/UserServiceC1_2#-770155619], message : ServiceContext [id=2e6fcef3852a48eeb7cb182d2bd62ef4, flowName=flower_test, currentServiceName=UserServiceC1, sync=false, attachments=null, flowMessage=FlowMessage [transactionId=52565043086d49abaa2ca88c3527883e, message=[B@76ecc10a], web=null], sender : Actor[akka://flower/user/flower/UserServiceB_2#1505663876]
2019-07-11 15:13:21.969 [flower-dispatcher-19] INFO  c.ly.train.flower.base.service.user.UserServiceC1 - 结束处理消息, message : User [name=响应式编程 , desc= --> UserServiceA --> UserServiceB --> UserServiceC1, age=5]

免责声明:文章转载自《响应式微服务框架Flower——快速上手》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇使用Proteus模拟操作HDG12864F-1液晶屏【转】Javascript异步编程之setTimeout与setInterval下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

(一)SQL注入漏洞测试的方式总结

一、工具注入 1.SQLMap的作用 判断可注入的参数 判断可以用那种SQL注入技术来注入 识别出哪种数据库 根据用户选择,读取哪些数据(库、表、列、字段值...) 2.注入技术 【A】基于布尔的盲注(Boolean-Based Blind Injection): 可以根据返回页面判断条件真假的注入 【B】基于时间的盲注(Time-Based Bl...

MySQL 千万 级数据量根据(索引)优化 查询 速度

一、索引的作用索引通俗来讲就相当于书的目录,当我们根据条件查询的时候,没有索引,便需要全表扫描,数据量少还可以,一旦数据量超过百万甚至千万,一条查询sql执行往往需要几十秒甚至更多,5秒以上就已经让人难以忍受了。 提升查询速度的方向一是提升硬件(内存、cpu、硬盘),二是在软件上优化(加索引、优化sql;优化sql不在本文阐述范围之内)。 能在软件上解决的...

Linux高级编程--04.GDB调试程序(查看数据)

查看栈信息 当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。你可以用GDB命令来查看当前的栈中的信息。 下面是一些查看函数调用栈信息的GDB命令: backtrace / bt :打印当前的函数调用栈的所有信息。如: (gdb) bt #0...

ZAB协议简介

Zookeeper 使用 Zookeeper Atomic Broadcast (ZAB) 协议来保障分布式数据一致性。 ZAB是一种支持崩溃恢复的消息广播协议,采用类似2PC的广播模式保证正常运行时性能,并使用基于 Paxos 的策略保证崩溃恢复时的一致性。 在阅读本文前建议先了解2PC和Paxos ZAB协议中节点存在四种状态: Leading: 当...

elixir mix开发入门

备注:  简单使用mix 进行项目的生成,同时添加docker 构建支持 1. 生成项目 mix new mydemoproject 输出信息如下: * creating README.md * creating .formatter.exs * creating .gitignore * creating mix.exs * cre...

WPF双向绑定

数据绑定模式共有四种:OneTime、OneWay、OneWayToSource和TwoWay,默认是TwoWay。 TwoWay 当发生更改时的目标属性或源属性更新目标属性。OneWay 仅当源属性更改时,请更新目标属性。OneTime 仅当应用程序启动时或时,请更新目标属性DataContext发生了更改。OneWayToSource 目标属性更改时,...