[翻译]squbs官网之2 Unicomplex & Cube 引导程序

squbs 带有一个默认的引导类 org.squbs.unicomplex.Bootstrap。可以从IDE、命令行、sbt、甚至Maven启动。引导程序扫描类加载器并在每个加载的 jar 包中查找META-INF/squbs-meta.<ext>。如果 squbs 元数据可用, 则 jar 包将被视为 squbs cube或扩展, 并根据元数据声明进行初始化。然后, 引导程序首先初始化扩展、cubes, 然后是服务处理程序, 而不管它们在类路径中的顺序如何。

在正常情况下, 引导细节没有多大意义。然而,可能需要以编程方式用不同的方案引导 squbs。这在需要自定义配置且需要并行运行的测试用例中尤其常见。有关详细信息, 请参阅测试。引导 squbs 的语法如下:

选项1)使用自定义配置启动

UnicomplexBoot(customConfig)
  .createUsing {(name, config) => ActorSystem(name, config)}
  .scanResources()
  .initExtensions
  .stopJVMOnExit
  .start()

选项2)使用默认配置启动

UnicomplexBoot {(name, config) => ActorSystem(name, config)}
  .scanResources()
  .initExtensions
  .stopJVMOnExit
  .start() 

1.创建UnicomplexBoot (boot)对象。通过传入一个自定义配置或者ActorSystem创建闭包给UnicomplexBoot.apply(),完成。
2.在上面的示例中显示为 customConfig 的配置对象。它是一个从Typesafe Config 库的解析函数获取的配置对象。此配置对象尚未与reference.conf合并。它是可选的,替代其它 application.conf 配置中的定义。
3.传入一个函数或闭包来创建ActorSystem。实际创建发生在启动阶段(下面第7项)。默认的函数是{(name, config) => ActorSystem(name, config)}。传入的名称是从配置文件中读取的ActorSystem名称。这个config是所有配置合并后加载的配置对象。大多数用例都希望以这种方式创建 ActorSystem, 因此不需要提供函数。createUsing可以完全避免。
4.使用scanResources()函数扫描组件查找cubes、服务或者扩展。这是强制性的, 否则将不启动任何组件。如果没有传递参数, squbs 引导程序将扫描其类加载器。测试用例可能希望只针对某些组件进行扫描。可以传入另外的squbs-meta.conf文件位置(作为scanResources的一个变量参数),例如.scanResources("component1/META-INF/squbs-meta.conf", "component2/META-INF/squbs-meta.conf")。将扫描你的类路径以及另外所给资源。如果你不想扫描类路径,传入withClassPath = false 或者在资源列表前的第一个参数仅传入false:.scanResources(withClassPath = false, "component1/META-INF/squbs-meta.conf", "component2/META-INF/squbs-meta.conf")
5.使用initExtension函数初始化扩展。将初始化扫描到的所有扩展。扩展的初始化将在ActorSystem创建前完成。对于多个Unicomplex用例(即多个ActorSystem),同一扩展不能多次初始化。一个扩展只能由一个测试用例使用。在某些测试用例中, 我们根本不希望初始化扩展, 也不会调用 initExtension。
6.在退出时停止 JVM。这是通过调用stopJVMOnExit函数来启用的。通常不应将此选项用于测试用例。它是由 squbs 的引导使用, 以确保 squbs 关闭和正确退出。
7.通过调用start()启动Unicomplex。这是一个强制性的步骤。没有它,没有ActorSystem启动,没有Actor运行。在系统完全启动和运行之前, start调用会阻塞或者产生一个超时。当启动超时时, 某些组件可能仍在初始化, 使系统处于Initializing状态。然而,任何单个组件故障都将使系统在超时时状态为Failed。这将允许系统组件 (如系统诊断程序) 运行并完成。默认的启动超时设置为60秒。对于预期超时的测试, 可以设置更小的值,通过向start()传入要求的超时,例如start(Timeout(5 seconds))或更短的start(5 seconds)(使用从duration到timeout的隐式转换)。

配置解析
squbs 选择一个应用程序配置, 并将其与类路径下的聚合的application.confreference.conf合并。正在合并的应用程序配置从以下顺序选择:
1.如果创建boot对象时提供了一个配置,这个配置将被选中。即上例中的customConfig字段。
2.如果在外部配置目录中提供了application.conf文件, 则此application.conf将被选中。外部配置目录是通过设置squbs.external-config-dir来配置的,默认是squbsconfig。不可以通过提供的配置或外部配置来更改或重写此目录(因为目录本身是使用配置属性确定的)。
3.否则,将使用与应用程序一起提供的application.conf(如果有将使用)。然后,回到reference.conf

模块化系统
squbs将应用划分到称为cube的模块中。squbs中的模块旨在以模块化隔离以及类路径上运行。模块隔离目的在真正的模块间松耦合,不会由于依赖出现任何类路径冲突。

当前实现的引导程序,来自于类路径。在引导时,squbs通过类路径扫描自动检测模块。扫描到的cube自动被检测并启动。

Cube Jar包
所有cube由一个含有cube逻辑的顶级jar包表示。都必须有cube元数据,存在于META-INF/squbs-meta.<ext>。支持的扩展名包括.conf, .json, .properties。格式遵守Typesafe配置格式。

至少,cube元数据唯一标识cube和版本,并声明以下一个或多个:

Actor:标识 squbs 自动启动的众所周知的actor。

Service:标识一个squbs服务。

Extension:标识一个squbs框架扩展。扩展入口点必须继承于org.squbs.lifecycle.ExtensionLifecycle特质。

配置解析
为一个cube提供application.conf,当多个cube试图提供它们内部的application.conf会导致问题。合并此类配置的优先级规则没有定义。推荐cube仅提供一个reference.conf,并且可以被外部application.conf覆盖以进行部署。

众所周知的actor
Well known actor只是Akka文档所定义的Akka actors。它们由一个监管actor(为每一个cube创建)启动。监管者持有cube名称。因此,任何well known actor有一个/<CubeName>/<ActorName>路径,并且可以使用ActorSelection调用(使用/user/<CubeName>/<ActorName>)。

一个well known actor可以由单例actor或者路由器启动。为了将一个well known actor声明为一个路由器,在actor声明中增加with-router = true。对于well known actor路由器、调度器和邮件按照Akka文档配置在reference.conf 或application.conf 。

下面是一个META-INF/squbs-meta.conf中的cube声明,申明了一个well known actor:

cube-name = org.squbs.bottlecube
cube-version = "0.0.2"
squbs-actors = [
  {
    class-name = org.squbs.bottlecube.LyricsDispatcher
    name = lyrics
    with-router = false  # Optional, defaults to false
    init-required = false # Optional
  }
]

init-required的参数用于需要发回其完全初始化状态的actor, 以便将系统视为已初始化。有关启动/初始化挂钩的完整讨论, 请参阅运行时生命周期和 API 文档的启动挂钩部分。

如果一个actor配置了with-router (with-router = true)和一个非默认调度器,通常意味着在非默认调度器上安排actor(即rootee)。路由器将假定well known actor名称, 而不是 routee (你的actor实现)。路由器上设置的调度器只会影响路由器, 而不是 routee。要影响 routee, 您需要为 routees 创建一个单独的配置, 并将 "/*" 追加到该名称。接下来, 您要将 routee 中的调度器配置为下面的示例。

akka.actor.deployment {

  # Router configuration
  /bottlecube/lyrics {
    router = round-robin-pool
    resizer {
      lower-bound = 1
      upper-bound = 10
    }
  }

  # Routee configuration. Since it has a '*', the name has to be quoted.
  "/bottlecube/lyrics/*" {
    # Configure the dispatcher on the routee.
    dispatcher = blocking-dispatcher
  }

Akka文档中记录了路由器概念、示例和配置。

服务
在实现HTTP(s)服务章节对服务有详细描述。在META-INF/squbs-meta.conf申明服务元数据,如下例所示:

cube-name = org.squbs.bottlesvc
cube-version = "0.0.2"
squbs-services = [
  {
    class-name = org.squbs.bottlesvc.BottleSvc
    web-context = bottles # You can also specify bottles/v1, for instance.

    # The listeners entry is optional, and defaults to 'default-listener'.
    listeners = [ default-listener, my-listener ]

    # Optional, defaults to a default pipeline.
    pipeline = some-pipeline

    # Optional, disables the default pipeline if set to off.  If missing, it is set to on.
    defaultPipeline = on

    # Optional, only applies to actors.
    init-required = false
  }
]

请看服务注册有详细描述。

扩展
squbs中的扩展是为了环境需要启动的低级别设施。扩展初始化器需要继承于org.squbs.lifecycle.ExtensionLifecycle特质并覆盖合适的回调。扩展有很大的能力来内省系统,并提供额外的功能,而这些squbs本身并没有提供。在同一个cube中,不能将扩展与actor或服务组合在一起。

扩展依次开始, 一个接着一个。扩展的提供者可以在扩展申明中提供一个序列号码在扩展启动时指定:sequence = [number]。如果没有指定序列号,则默认为Int.maxValue。这意味着它将在所有提供序列号的扩展之后启动。如果有多个扩展不指定序列号或指定相同的序列号, 则启动这些扩展的顺序是随机的。关机顺序与启动顺序相反。

关闭squbs
squbs运行时,可以向Unicomplex()发送GracefulStop消息来正确关闭squbs。

默认的启动主方法,org.squbs.unicomplex.Bootstrap,注册了一个JVM关闭钩子。因此,如果一个squbs应用使用了默认的main方法启动,当JVM收到SIGTERM时,会优雅的关闭。

如果某个其他监视进程负责关闭应用程序 (例如 JSW), 则可以将 org.squbs.unicomplex.Shutdown 设置为正常关闭系统的主要方法。此Shutdown main 方法也向 Unicomplex 发送 GracefulStop 消息。

在某些用例中, 最好为关机添加延迟。例如, 如果负载平衡器每5秒钟检查一次应用程序的运行状况, 并且应用程序在运行状况检查后关闭1秒, 应用程序将在接下来的4秒内继续收到请求, 直到下一次健康检查为止;但是, 它无法满足这些请求。如果使用上述方法之一 org.squbs.unicomplex.Bootstraporg.squbs.unicomplex.Shutdown, 则可以通过在配置中添加以下内容来增加关机的延迟:

squbs.shutdown-delay = 5 seconds

有了以上配置,向Unicomplex发送的GracefulStop消息将按计划推迟5秒发送。

在收到GracefulStop消息后,Unicomplex actor将停止服务并传播GracefulStop消息给所有的cube监管者。每一个监管者负责停止它cube内的actor(通过传播GracefulStop消息给它的想要优雅停止的孩子),确认它们成功的停止或者在超时后发送一个PoisonPill,然后停止它自己。一旦所有的cube监管者和服务停止,squbs系统关闭。然后,一个关闭钩将被调用,来停止所有的扩展并最终退出JVM。

web 容器目前没有标准的控制台, 允许 squbs 的用户自己构建。通过向Unicomplex发送停止消息, web 控制台可以提供正确的用户关闭, 如下所示:

Unicomplex() ! GracefulStop
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容