dapeng-soa服务生命周期

一个服务的前世今生-dapeng-soa服务生命周期详述

dapeng-soa architechure

1. 概述

随着搭载于dapeng框架之上的业务系统一个个上线并趋于稳定,不少开发同事们在抓虫子之余,也萌生了一些“不满”:用了dapeng好久了,但是它就像一个黑盒子,我们知之甚少,能否系统的介绍一下啊。
确实,dapeng框架提供了丰富的脚手架以及详尽的开发指南(详见dapeng官网), 极易上手。但了解一下dapeng的内部机制,有利于开阔眼界,并在开发中充分利用各个特性,对于提高服务的质量也很有好处。

本文着眼于分析一个服务从启动到结束的整个过程。

后续会分专题陆续介绍dapeng框架的各个特性,敬请留意。

2. dapeng 容器目录结构

dapeng-container
├── apps                           # 1. business services
│   ├── order_service
│   └── stock_service
├── bin
│   ├── dapeng-bootstrap.jar                      # 2. dapeng bootstrap module
│   ├── lib                                       # 3. dapeng container jars(including dependency)
│   ├── shutdown.sh                               # 4. startup/shutdown shell
│   └── startup.sh
├── conf                                          # 5. configuration files for container
│   └── logback.xml
├── lib                                           # 6. core lib
│   ├── dapeng-core-2.1.1.jar
│   └── logback-*.jar
├── logs                                          # 7. directory where log files located
└── plugin                                        # 8. plugin directory
  1. 业务服务,该目录由dapeng的ApplicationClassLoader加载, 可在一个dapeng容器中放多个服务,但是建议一个容器一个服务
  2. dapeng bootstrap模块,容器的启动入口,负责生成其它的定制classLoader并启动容器。
  3. dapeng container jar目录,容器的实现类及其三方依赖,通过ContainerClassLoader加载
  4. 启动以及停止脚本
  5. 容器的配置文件
  6. 核心接口库以及日志,由CoreClassLoader负责加载,可用于服务端以及客户端
  7. 日志目录
  8. 插件目录,由PluginClassLoader加载

注意, 不同的目录由不同的classLoader加载。常见的错误是:apps路径下的服务有个对象(通过ApplicationClassLoader加载),假设叫a,其类型为A,它是单例对象(通过A.getInstance()获得)。但是在bin路径下(也就是通过ContainerClassLoader加载), 通过A.getInstance()得到的a‘, 就跟a是完全不同的对象了。

3. zk节点结构

/soa/
├── runtime/service/                                   # 1. runtime info
│   ├── com.today.soa.idgen.service.IDService/
│   │   ├── 192.168.10.130:9081:1.0.0:0000000181        # 2. node info
│   │   ├── 192.168.20.101:9081:1.0.0:0000000179        # 3. master node
│   │   └── 192.168.10.138:9081:1.0.0:0000000183
│   ├── com.today.api.order.service.OrderService2/
│   │   ├── 192.168.10.133:9099:1.0.0:0000000368
│   │   ├── 192.168.10.126:9099:1.0.0:0000000372
│   │   ├── 192.168.20.102:9099:1.0.0:0000000367
│   │   └── 192.168.10.131:9099:1.0.0:0000000366        # master node
│   └── ...                                             # 4. other services
└── config/
    ├── services/                                       # 5. config info
    │   ├── com.today.soa.idgen.service.IDService
    │   └── com.today.api.order.service.OrderService2
    ├── freq/                                           # 6. rate limit rules
    ├── routes/                                         # 7. router rules
    └── cookies/                                        # 8. cookie rules

3.1 服务运行时信息 /soa/runtime/service/

服务运行时信息由服务在启动的时候注册到zk的/soa/runtime/service/${serviceName}路径上,其表现形式为挂靠在该路径下的临时节点,格式为:ip:port:version:seq, seq由zookeeper自动生成,且能保证在同目录下唯一并单调递增。
其中,dapeng容器根据本容器中服务运行时信息的seq,判断是否为master主节点(seq最低者为master)

一个服务对应一个临时节点。 我们可通过该路径得知目前服务集群中该服务的节点数量

3.2 服务配置信息 /soa/config/

服务配置信息存放了dapeng-soa所需要的一些配置项,可通过命令行工具或者配置中心进行管理。

服务的配置信息当前有四种,分布在/soa/config/不同的子目录下。它们的结构都类似,都是把服务名字作为节点挂在配置子目录下,然后配置信息作为节点的内容。

3.2.1 普通配置信息 /soa/config/services/

包括负载均衡策略、服务超时等信息。
包含两个层次:

  • 全局性配置: 直接写进/soa/config/services/节点
timeout/100ms;loadbalance/LeastActive;
  • 服务私有配置: 写到具体的服务节点上, 例如/soa/config/services/com.today.api.order.service.OrderService2
timeout/100ms,createOrder:500ms,createOrderPayment:60000ms;loadbalance/LeastActive,createOrder:Random,createOrderPayment:RoundRobin;

3.2.2 限流配置信息 /soa/config/freq/

dapeng 的流控做在服务端,所以该节点只对服务端有效。
限流信息直接写在具体的服务节点上,例如如下订单的限流配置写在/soa/config/freq/com.today.api.order.service.OrderService2

[rule1]
match_app = listOrder # 针对具体方法限流
rule_type = callerIp # 对每个请求端IP
min_interval = 60,5  # 每分钟请求数不超过5次
mid_interval = 3600,100 # 每小时请求数不超过100次
max_interval = 86400,200 # 每天请求数不超过200次

[rule2]
match_app = * # 针对订单服务限流
rule_type = callerIp # 对每个请求端IP
min_interval = 60,600  # 每分钟请求数不超过600
mid_interval = 3600,10000 # 每小时请求数不超过1万
max_interval = 86400,80000 # 每天请求数不超过8万

详见dapeng-soa限流文档

3.2.3 路由配置信息 /soa/config/routes/

服务路由信息也是直接写在具体的服务节点上,例如下面订单的路由配置写在/soa/config/routes/com.today.api.order.service.OrderService2

method match r"create.*" => ip"192.168.10.0/24"
cookie_storeId match %"10n+1..6" => ip"192.168.20.128"

详见dapeng-soa路由文档

3.2.3 cookie 规则信息 /soa/config/cookies/

cookie规则信息也是直接写在具体的服务节点上,例如针对来自dapengCli的手工对订单接口的调用,我们为这些调用打开TRACE功能,那么我们把规则配置到/soa/config/cookies/com.today.api.order.service.OrderService2:

callerIp match ip"192.168.20.200" => c"thread-log-level#TRACE"

3. 容器的生命周期

容器提供了一个LifeCycleAware接口以及若干事件,在事件发生的时候会触发相应的业务逻辑。
业务可通过实现该接口, 做一些初始化以及清理的动作。

例如某服务的业务,只在主节点启动一个工作线程。那么它就可以监听MASTER_CHANGE事件。当主节点发生变更的时候,就启动或者停止工作线程。

    public enum LifeCycleEventEnum {
        /**
         * dapeng 容器启动
         */
        START,
        PAUSE,
        MASTER_CHANGE,
        CONFIG_CHANGE,
        STOP
    }
/**
 * 提供给业务的lifecycle接口,四种状态
 *
 * @author hui
 * @date 2018/7/26 11:21
 */
public interface LifeCycleAware {

    /**
     * 容器启动时回调方法
     */
    void onStart(LifeCycleEvent event);

    /**
     * 容器暂停时回调方法
     */
    default void onPause(LifeCycleEvent event) {
    }

    /**
     * 容器内某服务master状态改变时回调方法
     * 业务实现方可自行判断具体的服务是否是master, 从而执行相应的逻辑
     */
    default void onMasterChange(LifeCycleEvent event) {
    }

    /**
     * 容器关闭
     */
    void onStop(LifeCycleEvent event);

    /**
     * 配置变化
     */
    default void onConfigChange(LifeCycleEvent event) {
    }
}

4. 容器的启动过程

容器启动需要协调各个插件的顺序,避免在服务还没准备好的情况下,客户端请求就涌进来。
通过脚本startup.sh启动容器: java -server $JAVA_OPTS -cp ./dapeng-bootstrap.jar com.github.dapeng.bootstrap.Bootstrap

dapeng-soa bootstrap

  1. Bootstrap创建三个classLoader, 分别是CoreClassLoader(负责加载lib目录的类)、ContainerClassLoader(负责加载bin/lib目录的类)以及ApplicationClassLoader(负责加载apps目录下的类)。
  2. Bootstrap通过ContainerClassLoader加载ContainerFactory并调用其getContainer方法, 获得DapengContainer实例。
  3. DapengContainer创建五个Plugin,并依次调用其start方法:
    3.1 启动NettyPlugin, 打开服务监听端口(例如9090)
    3.2 启动ZkPlugin, 跟注册中心zookeeper建立连接。
    3.3 启动SpringPlugin
    3.3.1 通过ApplicationClassLoader加载服务(一个服务表现为一个Application对象)
    3.3.2 对每个服务(假设为OrderService),通过ZkPlugin把服务信息注册到/soa/runtime/service/com.today.api.order.service.OrderService2目录里,并启动一个对该路径的zk watcher(主要用于跟踪服务集群中master节点的变化, 当发生master变换时,需触发MASTER_CHANGE事件。

    一旦服务完成注册,嗷嗷待哺的客户端就会如潮水般涌进该服务节点。

    3.4 启动SchedulePlugin, 定时任务就绪
    3.5 启动JmxPluginJmx 端口就绪
    3.6 如果是开发模式(默认), 那么启动ApiDocPlugin, 内置的文档站点可访问。该插件在生产环境下不会启动

  4. 触发容器START事件
  5. 加载服务端Filter(详情下回分解)。
  6. 最后,注册Jvm进程的ShutdownHook

至此,容器启动完毕, 服务生命周期开始。

5. 容器的优雅关闭过程

容器的关闭过程,同样需要协调插件的关闭顺序,确保进来的请求尽量处理完毕后再关闭容器,避免对业务产生影响。为此, dapeng 容器会维护一个请求计数器requestCounter,计数值是当前容器内尚未处理完的请求数目。

  1. 启动脚本startup.sh会监听kill信号。收到kill信号后,脚本转发该信号到容器Jvm进程。
  2. 容器的ShutdownHook给触发,依次执行:
    2.1 ZkPlugin.stop方法,断开跟zookeeper的连接,从而把本节点服务信息从/soa/runtime/services/${serviceName}上摘除,进而新的请求就不会再路由到本节点。
    2.2 休眠若干次,直到requestCounter数目为0或者超时。
    2.3 关闭其它插件( Netty有自己的优雅关闭机制,能确保outbound队列的消息能全部发送出去)

至此,容器关闭,服务结束了其使命。

原文地址:https://www.cnblogs.com/sea520/p/12165737.html

时间: 2024-08-30 13:31:07

dapeng-soa服务生命周期的相关文章

Android开发之旅(二)服务生命周期和广播接收者生命周期

引言 应用程序组件有一个生命周期——一开始Android实例化他们响应意图,直到结束实例被销毁.在这期间,他们有时候处于激活状态,有时候处于非激活状态:对于活动,对用户有时候可见,有时候不可见.组件生命周期将讨论活动.服务.广播接收者的生命周期——包括在生命周期中他们可能的状态.通知状态改变的方法.及这些状态的组件寄宿的进程被终结和实例被销毁的可能性. 上篇Android开发之旅:组件生命周期(一)讲解了论活动的生命周期及他们可能的状态.通知状态改变的方法.本篇将介绍服务和广播接收者的生命周期:

ITIL - 服务生命周期(Service Lifecycle)

/** * 作者: 启卫 * 时间: 2017年6月15号 * 主要内容: IT服务生命周期管理 *     - 定义服务生命周期 *     - ITIL服务管理实践 *    -  为什么使用ITIL? *    -  关键术语 **/ 一.ITIL服务管理最佳实践 ITIL 与 标准化的思维: * 你不必严格遵守ITIL * IT组织可以参考IT标准 * 关键原理.必要的流程 以及 活动 * 组织 与 角色 * 技术 与 挑战 * 成功的因素 与 风险 为何使用ITIL? * ITIL 使

构造函数的选择与服务生命周期管理

构造函数的选择与服务生命周期管理 ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationInstance和ImplementationFactory属性均为Null,那么ServiceProvider最终会利用其ImplementationType属性返回的真实类型选择一个适合的构造函数来创建最终的服务实例.我们知道服务服务的真实类型可以定义了多个构造函

(3)Asp.Net Core 服务生命周期

1.前言 在ConfigureServices方法中的容器注册每个应用程序的服务,Asp.Core都可以为每个应用程序提供三种服务生命周期:●Transient(暂时):每次请求都会创建一个新的实例.这种生命周期最适合轻量级,无状态服务.●Scoped(作用域):在同一个作用域内只初始化一个实例 ,可以理解为每一个请求只创建一个实例,同一个请求会在一个作用域内.●Singleton(单例):整个应用程序生命周期以内只创建一个实例,后续每个请求都使用相同的实例.如果应用程序需要单例行为,建议让服务

Siemens PLM TeamCenter 9.1生命周期管理软件

Siemens PLM TeamCenter 9.1生命周期管理软件Teamcenter 在构建时充分考虑了可扩展性. 无论是需要小规模部署来支持单个站点的小型团队,还是拥有遍布全球的众多站点以及复杂供应链的大型企业,或者介于其间的任何公司,Teamcenter 灵活的体系架构都能满足您当前的业务需求,并能随着贵公司的增长而继续保持出色表现. 下载内容包括: Siemens PLM TeamCenter 9.1 32和64位 为多国语言版本 Disc3 和 Disc4安装包 Teamcenter

17.(转) Android之四大基本组件介绍与生命周期

Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器. 一:了解四大基本组件 Activity : 应用程序中,一个Activity通常就是一个单独的屏幕,它上面可以显示一些控件也可以监听并处理用户的事件做出响应. Activity之间通过Intent进行通信.在Intent 的描述结构中,有两个最重要的部分:动作和动作对应的数据. 典型的动作类型有:M AIN(activity的门户).V

Service的生命周期&Service绑定方法

服务的生命周期: 一.采用start的方式开启服务 生命周期如下: 开启服务: onCreate()--> onStartCommand() (onStart()过时了)---> onDestory(): 如果服务已经开启,不会重复的执行onCreate(), 而是会调用onStart()和 onStartCommand(); 服务停止的时候 onDestory(). 服务只会被停止一次 二.采用绑定的方式开启服务.onCreate() --->onBind()--->onunbi

四大组件的生命周期

原文转自:http://www.cnblogs.com/bravestarrhu/archive/2012/05/02/2479461.html 介绍生命周期之前,先提一下任务的概念 任务其实就是activity 的栈它由一个或多个Activity组成的共同完成一个完整的用户体验, 换句话说任务就是” 应用程序” (可以是一个也可以是多个,比如假设你想让用户看到某个地方的街道地图.而已经存在一个具有此功能的activity 了,那么你的activity 所需要做的工作就是把请求信息放到一个Int

Android四大组件的生命周期

介绍生命周期之前,先提一下任务的概念 任务其实就是activity 的栈它由一个或多个Activity组成的共同完成一个完整的用户体验, 换句话说任务就是" 应用程序" (可以是一个也可以是多个,比如假设你想让用户看到某个地方的街道地图.而已经存在一个具有此功能的activity 了,那么你的activity 所需要做的工作就是把请求信息放到一个Intent 对象里面,并把它传递给startActivity().于是地图浏览器就会显示那个地图.而当用户按下BACK 键的时候,你的act