
后端并发编程异步编程【免费下载链接】akka-coreA platform to build and run apps that are elastic, agile, and resilient. SDK, libraries, and hosted environments.项目地址https://gitcode.com/gh_mirrors/ak/akka-core点击查看免费下载Akka 在设计上做到了零配置即可启动——所有模块都内置了合理默认值但真实的生产环境通常需要调整日志级别、启用集群、配置序列化器或调优调度器。本文以 Akka 官方配置文档为主体结合仓库内的默认配置reference.conf与源码实现系统讲解 Akka 配置的加载机制、覆盖优先级、License 校验、自定义配置、多 ActorSystem 隔离以及排查配置问题的方法读完即可独立完成从入门到生产级的配置管理工作。配置从哪里读取ActorSystem 与 Typesafe ConfigAkka 的全部配置都存放在ActorSystem实例内部。从外部视角看ActorSystem是配置信息的唯一消费者构建 ActorSystem 时你可以显式传入一个com.typesafe.config.Config对象也可以什么都不传——后者等价于传入ConfigFactory.load()使用正确的 ClassLoader。Akka 使用 Typesafe Config Library纯 Java 实现、无外部依赖作为配置库这一点同样适用于你自己基于 Akka 或独立构建的应用与库。该库的完整能力远超本文范围这里只总结最关键的部分。默认情况下ConfigFactory.load()会解析 classpath 根目录下所有的application.conf、application.json和application.properties。随后 ActorSystem 会把 classpath 根目录下发现的所有reference.conf资源合并进来作为回退fallback配置其内部逻辑等价于appConfig.withFallback(ConfigFactory.defaultReference(classLoader))这一设计哲学非常明确代码中永远不写默认值默认值一律存放在随库分发的reference.conf中。在 akka-actor 的 reference.conf 第 1-7 行的注释就写明了这一点This is the reference config file that contains all the default settings. Make your edits/overrides in your application.conf.而它的真实加载点位于 ActorSystem.scalafinal val settings: Settings { val config Settings.amendSlf4jConfig( applicationConfig.withFallback(ConfigFactory.defaultReference(classLoader)), _dynamicAccess) new Settings(classLoader, config, name, setup) }优先级与覆盖规则配置合并遵循严格的优先级从高到低为系统属性system properties覆盖——优先级最高见 HOCON 规范应用配置——默认是application即application.conf/application.json/application.propertiesreference.conf默认值——每个库自带优先级最低。此外应用配置的资源名可以通过config.resource属性覆盖还有其他相关属性详见 Typesafe Config 文档。注意如果你在编写 Akka 应用请把配置放在 classpath 根目录的application.conf中如果你在编写基于 Akka 的库请把配置放在 JAR 文件根目录的reference.conf中。不支持在一个库的reference.conf里覆盖另一个库拥有的配置属性——因为合并顺序不确定时最终生效值将变得不可预测。这一约束在 默认配置参考页 中同样被明确强调。许可证密钥License keyAkka 在生产环境使用需要许可证密钥免费密钥可在 https://akka.io/key 获取。把密钥写入配置属性akka.license-key即可akka.license-key your-key-here在 akka-actor 的 reference.conf 中相关的默认配置如下# The license key to use Akka. Free keys at https://akka.io/key license-key # If false, will not warn if there is no Akka license. Note, this only # suppresses the log messages, it does not stop the actor system from # terminating. warn-on-no-license-key true没有密钥或密钥过期会怎样本地开发没有密钥也能使用 Akka但要注意——未配置密钥时ActorSystem会在一段时间后自动终止约 15 分钟。密钥过期如果在启动 ActorSystem 时密钥已经过期系统也会在一段时间后终止。这些行为的底层实现可以在 ActorSystem.scala 的 checkLicenseKey 方法 中找到。未配置密钥时系统会记录 Dev use only. Free keys at https://akka.io/key 警告然后通过scheduler.scheduleOnce(15.minutes)调度一次终止。如果akka.warn-on-no-license-key设为false只会抑制日志输出并不会阻止 ActorSystem 终止。当配置了密钥时Akka 会用内置的 EC 公钥对密钥做 Base62 解码与 SHA256withECDSA 签名校验解析出许可证的用户、签发方Akka 或 Kalix、构建过期日期与有效期等声明并校验密钥是否被吊销、是否与当前 Akka 版本匹配详见 ActorSystem.scala。如何编程读取密钥过期时间过期日期通过ActorSystem.licenseKeyExpiryScala API返回Option[LocalDate]或ActorSystem.getLicenseKeyExpiry()Java API返回OptionalLocalDate暴露。注意密钥是永久的perpetual key时返回None/Optional.empty未定义密钥时过期日期是今天。你可以在 CI/CD 集成中写一个测试在密钥到期前一个月就让它开始失败提醒自己及时续期。完整的可运行示例见 ConfigDocSpec.scala 和 ConfigDocTest.javaScalaval system ActorSystem(rootBehavior, name) val licenseKey system.licenseKeyExpiry licenseKey.isEmpty shouldBe false import java.time.LocalDate val nextMonth LocalDate.now().plusMonths(1) licenseKey.get.isAfter(nextMonth) shouldBe true system.terminate()JavaActorSystemVoid system ActorSystem.create(rootBehavior, name); OptionalLocalDate licenseKey system.getLicenseKeyExpiry(); assertFalse(licenseKey.isEmpty()); LocalDate nextMonth LocalDate.now().plusMonths(1); assertTrue(licenseKey.get().isAfter(nextMonth)); system.terminate();使用 JarJar、OneJar、Assembly 等打包工具时警告Akka 的配置机制高度依赖每个模块/JAR 都有自己的reference.conf这一约定。所有reference.conf都会被配置系统发现并加载。因此如果你把多个 JAR 合并进同一个 JAR必须同时合并所有的reference.conf文件否则所有默认值都会丢失。关于打包时如何合并reference.conf资源请参阅部署文档。自定义 application.conf一份自定义的application.conf长这样——你可以在其中覆盖 reference 文件中定义的任何选项# In this file you can override any option defined in the reference files. # Copy in parts of the reference files and modify as you please. akka { # Logger config for Akka internals and classic actors, the new API relies # directly on SLF4J and your config for the logger backend. # Loggers to register at boot time (akka.event.Logging$DefaultLogger logs # to STDOUT) loggers [akka.event.slf4j.Slf4jLogger] # Log level used by the configured loggers (see loggers) as soon # as they have been started; before that, see stdout-loglevel # Options: OFF, ERROR, WARNING, INFO, DEBUG loglevel DEBUG # Log level for the very basic logger activated during ActorSystem startup. # This logger prints the log messages to stdout (System.out). # Options: OFF, ERROR, WARNING, INFO, DEBUG stdout-loglevel DEBUG # Filter of log events that is used by the LoggingAdapter before # publishing log events to the eventStream. logging-filter akka.event.slf4j.Slf4jLoggingFilter actor { provider cluster default-dispatcher { # Throughput for default Dispatcher, set to 1 for as fair as possible throughput 10 } } remote.artery { # The port clients should connect to. canonical.port 4711 } }对照 akka-actor 的 reference.conf 可以看到每个选项的默认值loglevel默认INFO、stdout-loglevel默认WARNING、loggers默认[akka.event.Logging$DefaultLogger]、logging-filter默认akka.event.DefaultLoggingFilter、actor.provider默认localremote与cluster需要 classpath 上有 akka-remote 和 akka-cluster 构件、default-dispatcher.throughput默认 5。这些默认值都以带详细注释的形式存在 reference.conf 中是排查为什么行为与预期不符的第一手资料。包含include其他配置文件有时把另一个配置文件包含进来很有用。例如你有一个包含所有环境无关设置的application.conf再针对特定环境覆盖部分设置。通过-Dconfig.resource/dev.conf指定系统属性会加载dev.conf文件而dev.conf可以 include 进application.confdev.confinclude application akka { loglevel DEBUG }更高级的 include 与替换substitution机制参见 HOCON 规范。include 的位置也很关键application.conf顶部的 include 会被文件其余部分覆盖底部的 include 则会覆盖之前的设置同样在使用-Dconfig.resource指定替换文件时include application之前的设置会被被包含文件覆盖之后的设置会覆盖被包含文件。配置的日志输出log-config-on-start如果你不确定当前实际生效的配置是什么可以把系统属性或配置项akka.log-config-on-start设为onActorSystem 启动时就会在 INFO 级别打印完整配置。对应的默认值为off见 reference.conf。在 REPL 中检查配置对象如果存有疑问你可以在构建 ActorSystem 之前或之后检查配置对象。在 Scala REPL 中scala import com.typesafe.config._ import com.typesafe.config._ scala ConfigFactory.parseString(a.b12) res0: com.typesafe.config.Config Config(SimpleConfigObject({a : {b : 12}})) scala res0.root.render res1: java.lang.String { # String: 1 a : { # String: 1 b : 12 } }每个条目前面的注释提供了该设置的**来源信息文件与行号**以及 reference 配置中附带的说明注释。而经过 ActorSystem 合并 reference 配置并解析后的完整设置可以这样打印Scalaval system ActorSystem(rootBehavior, MySystem) system.logConfiguration()JavaActorSystemVoid system ActorSystem.create(rootBehavior, MySystem); system.logConfiguration();完整示例见 ConfigDocSpec.scala 和 ConfigDocTest.java。关于 ClassLoader 的一点说明配置文件中多处允许指定某个类的全限定名由 Akka 通过 Java 反射实例化而反射依赖ClassLoader。在应用容器或 OSGi 这类复杂环境中拿到正确的 ClassLoader 并不总是容易的事。Akka 目前的策略是每个ActorSystem实现都会保存创建时当前线程的上下文类加载器如果可用否则用自己的类加载器即this.getClass.getClassLoader并用于所有反射访问。因此如果把 Akka 放到 boot classpath 上会从奇怪的地方抛出NullPointerException——这是不受支持的用法。此外ActorSystem也会把该上下文类加载器设置到其创建的所有线程上见 ActorSystem.scala 中dynamicAccess的注释说明。应用自身的配置项配置系统同样可以存放应用自身的设置。好的实践是把这些设置放进一个 Extension例如放在my.own.setting这样的自定义命名空间下由 Extension 统一读取与校验。配置多个 ActorSystem如果你有多个ActorSystem或者你在写一个库其中有一个与应用的 ActorSystem 相互独立的 ActorSystem你可能会希望为每个系统分开配置。由于ConfigFactory.load()会从整个 classpath 合并所有同名资源最简单的做法就是利用这一点在配置层级中用不同的子树区分各个 ActorSystemmyapp1 { akka.loglevel WARNING my.own.setting 43 } myapp2 { akka.loglevel ERROR app2.setting appname } my.own.setting 42 my.other.setting helloScalaval config ConfigFactory.load() val app1 ActorSystem(rootBehavior, MyApp1, config.getConfig(myapp1).withFallback(config)) val app2 ActorSystem(rootBehavior, MyApp2, config.getConfig(myapp2).withOnlyPath(akka).withFallback(config))JavaConfig config ConfigFactory.load(); ActorSystemVoid app1 ActorSystem.create(rootBehavior, MyApp1, config.getConfig(myapp1).withFallback(config)); ActorSystemVoid app2 ActorSystem.create( rootBehavior, MyApp2, config.getConfig(myapp2).withOnlyPath(akka).withFallback(config));完整示例见 ConfigDocSpec.scala 和 ConfigDocTest.java。这两个示例演示了提升子树lift-a-subtree技巧的两种变体第一种config.getConfig(myapp1).withFallback(config)会把myapp1子树提升到顶层再从完整配置回退。ActorSystem 内部可见的配置为akka.loglevel WARNING my.own.setting 43 my.other.setting hello // plus myapp1 and myapp2 subtrees第二种config.getConfig(myapp2).withOnlyPath(akka).withFallback(config)只提升myapp2子树中的akka部分结果如下akka.loglevel ERROR my.own.setting 42 my.other.setting hello // plus myapp1 and myapp2 subtrees注意Typesafe Config 库的功能非常强大全部讲解超出本文范围。这里特别不展开的是在文件内再 include 其他配置文件可参考上文 包含文件 的小例子以及通过路径替换path substitution复制配置树的某一部分。编程方式构造自定义配置你还可以在实例化ActorSystem时用其他方式编程指定和解析配置Scalaimport akka.actor.typed.ActorSystem import com.typesafe.config.ConfigFactory val customConf ConfigFactory.parseString( akka.log-config-on-start on ) // ConfigFactory.load sandwiches customConfig between default reference // config and default overrides, and then resolves it. val system ActorSystem(rootBehavior, MySystem, ConfigFactory.load(customConf))Javaimport akka.actor.typed.ActorSystem; import akka.actor.typed.Behavior; import akka.actor.typed.javadsl.Behaviors; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; Config customConf ConfigFactory.parseString(akka.log-config-on-start on); // ConfigFactory.load sandwiches customConfig between default reference // config and default overrides, and then resolves it. ActorSystemVoid system ActorSystem.create(rootBehavior, MySystem, ConfigFactory.load(customConf));这两个入口在 typed ActorSystem 的 apply 重载 中定义——不传 Config 的重载等价于传入ConfigFactory.load()传 Config 的重载则直接使用你提供的配置对象。从自定义位置读取配置你可以在代码中或通过系统属性替换或补充application.conf。如果你使用ConfigFactory.load()Akka 默认如此可以通过以下系统属性替换application.conf-Dconfig.resourcewhatever—— 替换为 classpath 上的指定资源-Dconfig.filewhatever—— 替换为文件系统上的指定文件-Dconfig.urlwhatever—— 替换为指定 URL 的资源。在由-Dconfig.resource等属性指定的替换文件内部如果你仍想使用application.{conf,json,properties}可以include application。代码中的多种定制方式ConfigFactory.load()有多个重载允许你在系统属性覆盖与默认值来自reference.conf之间夹入自定义内容取代通常的application.{conf,json,properties}以及-Dconfig.file等属性最简单的重载接收一个资源 basename而不是application例如传入myname就会使用myname.conf、myname.json和myname.properties最灵活的重载接收一个Config对象你可以用ConfigFactory的任意方法加载它——比如用ConfigFactory.parseString()在代码中内嵌配置字符串或用ConfigFactory.parseMap()从 Map 构造或直接加载文件。你还可以把自定义配置与常规配置组合起来例如Scala// make a Config with just your special setting val myConfig ConfigFactory.parseString(somethingsomethingElse); // load the normal config stack (system props, // then application.conf, then reference.conf) val regularConfig ConfigFactory.load(); // override regular stack with myConfig val combined myConfig.withFallback(regularConfig); // put the result in between the overrides // (system props) and defaults again val complete ConfigFactory.load(combined); // create ActorSystem val system ActorSystem(rootBehavior, myname, complete);Java// make a Config with just your special setting Config myConfig ConfigFactory.parseString(somethingsomethingElse); // load the normal config stack (system props, // then application.conf, then reference.conf) Config regularConfig ConfigFactory.load(); // override regular stack with myConfig Config combined myConfig.withFallback(regularConfig); // put the result in between the overrides // (system props) and defaults again Config complete ConfigFactory.load(combined); // create ActorSystem ActorSystem system ActorSystem.create(rootBehavior, myname, complete);完整示例见 ConfigDocSpec.scala 和 ConfigDocTest.java。配置的三层蛋糕模型操作Config对象时请记住配置栈的三个层级ConfigFactory.defaultOverrides()—— 系统属性优先级最高应用自身的设置中间层默认来自application.confConfigFactory.defaultReference()——reference.conf优先级最低。通常的目标是定制中间层同时保持另外两层不动ConfigFactory.load()加载整个配置栈ConfigFactory.load()的重载允许你指定不同的中间层ConfigFactory.parse*系列变体只加载单个文件或资源。要叠加两层使用override.withFallback(fallback)——尽量把系统属性defaultOverrides()放在顶层、把reference.confdefaultReference()放在底层。另外请记住很多情况下你只需要在application.conf里加一条include语句而不必写代码。Reference 配置清单每个 Akka 模块都有一个包含默认值的reference.conf文件。例如 akka-actor/src/main/resources/reference.conf 定义了日志、调度器dispatcher、路由器router、序列化器、调度器scheduler、IO 等核心默认值akka-remote、akka-cluster、akka-persistence、akka-stream 等模块也各自带有一份。完整的模块清单及逐项配置说明请查阅 默认配置Default configuration。该页面还提示如果你不确定覆盖某个默认值的后果就不要轻易覆盖Akka Config Checker 是查找潜在配置问题的实用工具。小结配置实战要点默认值来自reference.conf代码中不含默认值应用覆盖写在application.conf库的默认值写在自身的reference.conf且不要跨库覆盖属性。优先级系统属性 应用配置application.confreference.conf。生产环境记得配置akka.license-key并用licenseKeyExpiry/getLicenseKeyExpiry()写一个提前一个月告警的测试。多 JAR 合并打包时务必合并所有reference.conf否则默认值全部丢失。不确定生效配置时设置akka.log-config-on-start on或调用system.logConfiguration()打印完整配置配置对象render时每个条目都会标注来源文件与行号。多 ActorSystem 场景用getConfig(myapp).withFallback(config)/withOnlyPath(akka)的提升子树技巧隔离配置。更换配置来源命令行用-Dconfig.resource/-Dconfig.file/-Dconfig.url代码中用ConfigFactory.load(自定义Config)的各类重载。赞分享后端并发编程异步编程【免费下载链接】akka-coreA platform to build and run apps that are elastic, agile, and resilient. SDK, libraries, and hosted environments.项目地址https://gitcode.com/gh_mirrors/ak/akka-core点击查看免费下载相关推荐rust-analyzer 配置完全指南从 LSP initializationOptions 到 rust-analyzer.toml 的完整配置体系rust analyzer 配置完全指南从 LSP initializationOptions 到 rust analyzer.toml 的完整配置体系 本文开发工具FrankenPHP 配置完全指南从 Caddyfile 到 PHP 运行时的完整配置体系FrankenPHP 配置完全指南从 Caddyfile 到 PHP 运行时的完整配置体系 导读 FrankenPHP 将 PHP 解释器直接嵌入 Caddy后端Akka Typed 日志Logging完整实践指南从 ActorContext 到 SLF4J 后端配置Akka Typed 日志Logging完整实践指南从 ActorContext 到 SLF4J 后端配置 本文基于 Akka 官方文档 typed/lo后端并发编程异步编程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考