# 配置 你可以在不定义任何配置的情况下开始使用 Akka,因为提供了合理的默认值。稍后,你可能需要修改设置以更改默认行为或适应特定的运行时环境。你可以修改的典型设置示例: - 日志级别和日志记录器后端 - 启用远程处理 - 消息序列化程序 - 路由器的定义 - 调度员调整 Akka 使用「[Typesafe Config Library](https://github.com/lightbend/config)」,这对于配置你自己的应用程序或使用或不使用 Akka 构建的库也是一个不错的选择。这个库是用 Java 实现的,没有外部依赖关系;你应该看看它的文档,特别是关于「[ConfigFactory](https://lightbend.github.io/config/latest/api/com/typesafe/config/ConfigFactory.html)」。 - **警告**:如果你使用来自`2.9.x`系列的 Scala REPL 的 Akka,并且没有向`ActorSystem`提供自己的`ClassLoader`,那么需要使用`-Yrepl-sync`启动 REPL,以解决 REPLs 提供的上下文类加载器中的缺陷。 ## 从哪里读取配置? Akka 的所有配置(`configuration`)都保存在`ActorSystem`实例中,或者换句话说,从外部看,`ActorSystem`是配置信息的唯一使用者。在构造 Actor 系统时,可以传入`Config`对象,也可以不传入,其中第二种情况等同于传递`ConfigFactory.load()`,使用正确的类加载器。这大致意味着默认值是解析类路径根目录下的所有`application.conf`、`application.json`和`application.properties`文件。有关详细信息,请参阅上述文档。然后,Actor 系统合并在类路径根目录下找到的所有`reference.conf`资源,以形成最终的配置,以供内部使用。 ```java appConfig.withFallback(ConfigFactory.defaultReference(classLoader)) ``` 其原理是代码从不包含默认值,而是依赖于它们在相关库提供的`reference.conf`中的存在。 作为系统属性给出的覆盖具有最高优先级,请参阅「[HOCON](https://github.com/lightbend/config/blob/master/HOCON.md)」规范(靠近底部)。另外值得注意的是,默认为应用程序的应用程序配置可以使用`config.resource`属性覆盖,还有更多内容,请参阅「[Config](https://github.com/lightbend/config/blob/master/README.md)」文档。 - **注释**:如果你正在编写 Akka 应用程序,请将你的配置保存在类路径根目录下的`application.conf`中。如果你正在编写基于 Akka 的库,请将其配置保存在 JAR 文件根目录下的`reference.conf`中。 ## 使用 JarJar、OneJar、Assembly 或任何 jar-bundler 时 - **警告**:Akka 的配置方法很大程度上依赖于每个`module/jar`都有自己的`reference.conf`文件的概念,所有这些都将由配置发现并加载。不幸的是,这也意味着如果你将多个 Jar 放入或合并到同一个 Jar 中,那么你还需要合并所有`reference.conf`。否则,所有默认值将丢失,Akka 将不起作用。 如果使用 Maven 打包应用程序,还可以使用「[Apache Maven Shade Plugin](http://maven.apache.org/plugins/maven-shade-plugin/)」的「[Resource Transformers](http://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html#AppendingTransformer)」,其支持将构建类路径上的所有`reference.conf`合并为一个。 插件配置可能如下所示: ```xml org.apache.maven.plugins maven-shade-plugin 1.5 package shade true allinone *:* reference.conf akka.Main ``` ## 自定义 application.conf 一个自定义的`application.conf`配置可能如下所示: ``` # 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 { # 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 { # The port clients should connect to. Default is 2552. netty.tcp.port = 4711 } } ``` ## 包含文件 有时,包含另一个配置文件可能很有用,例如,如果你有一个`application.conf`,具有所有与环境无关的设置,然后覆盖特定环境的某些设置。 使用`-Dconfig.resource=/dev.conf`指定系统属性将加载`dev.conf`文件,其中包括`application.conf` - **dev.conf** ``` include "application" akka { loglevel = "DEBUG" } ``` 在 HOCON 规范中解释了更高级的包含和替换机制。 ## 配置日志记录 如果系统或配置属性`akka.log-config-on-start`设置为`on`,那么当 Actor 系统启动时,将在`INFO`级别记录完整配置。当你不确定使用了什么配置时,这很有用。 如果有疑问,你可以在使用配置对象构建 Actor 系统之前或之后检查它们: ``` Welcome to Scala 2.12 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0). Type in expressions to have them evaluated. Type :help for more information. scala> import com.typesafe.config._ import com.typesafe.config._ scala> ConfigFactory.parseString("a.b=12") 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 } } ``` 每个项目前面的注释给出了有关设置起点(文件和行号)的详细信息以及可能出现的注释,例如在参考配置中。合并引用和 Actor 系统的设置如下所示: ```java final ActorSystem system = ActorSystem.create(); System.out.println(system.settings()); // this is a shortcut for system.settings().config().root().render() ``` ## 关于类加载器的一句话 在配置文件的几个地方,可以指定由 Akka 实例化的某个对象的完全限定类名。这是使用 Java 反射完成的,Java 反射又使用类加载器。在应用程序容器或 OSGi 包等具有挑战性的环境中获得正确的方法并不总是很简单的,Akka 的当前方法是,每个`ActorSystem`实现存储当前线程的上下文类加载器(如果可用,否则只存储其自己的加载器,如`this.getClass.getClassLoader`)并将其用于所有反射访问。这意味着将 Akka 放在引导类路径上会从奇怪的地方产生`NullPointerException`:这是不支持的。 ## 应用程序特定设置 配置也可用于特定于应用程序的设置。一个好的做法是将这些设置放在「[扩展](https://codechina.csdn.net/monokai/akka-guide/blob/master/articles/index-utilities/extending-akka.md#%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E7%89%B9%E5%AE%9A%E8%AE%BE%E7%BD%AE)」中。 ### 配置多个 ActorSystem 如果你有多个`ActorSystem`(或者你正在编写一个库,并且有一个`ActorSystem`可能与应用程序的`ActorSystem`分离),那么你可能需要分离每个系统的配置。 考虑到`ConfigFactory.load()`从整个类路径中合并所有具有匹配名称的资源,利用该功能区分配置层次结构中的 Actor 系统是最容易: ``` myapp1 { akka.loglevel = "WARNING" my.own.setting = 43 } myapp2 { akka.loglevel = "ERROR" app2.setting = "appname" } my.own.setting = 42 my.other.setting = "hello" ``` ```java val config = ConfigFactory.load() val app1 = ActorSystem("MyApp1", config.getConfig("myapp1").withFallback(config)) val app2 = ActorSystem("MyApp2", config.getConfig("myapp2").withOnlyPath("akka").withFallback(config)) ``` 这两个示例演示了“提升子树(`lift-a-subtree`)”技巧的不同变化:在第一种情况下,从 Actor 系统中访问的配置是 ``` akka.loglevel = "WARNING" my.own.setting = 43 my.other.setting = "hello" // plus myapp1 and myapp2 subtrees ``` 在第二种情况下,只提升“akka”子树,结果如下 ``` akka.loglevel = "ERROR" my.own.setting = 42 my.other.setting = "hello" // plus myapp1 and myapp2 subtrees ``` - **注释**:配置库非常强大,说明其所有功能超出了本文的范围。尤其不包括如何将其他配置文件包含在其他文件中(参见「[包含文件](https://codechina.csdn.net/monokai/akka-guide/blob/master/articles/general-concepts/configuration.md#%E5%8C%85%E5%90%AB%E6%96%87%E4%BB%B6)」中的一个小示例)以及通过路径替换复制配置树的部分。 在实例化`ActorSystem`时,还可以通过其他方式以编程方式指定和分析配置。 ```java import akka.actor.ActorSystem import com.typesafe.config.ConfigFactory val customConf = ConfigFactory.parseString(""" akka.actor.deployment { /my-service { router = round-robin-pool nr-of-instances = 3 } } """) // ConfigFactory.load sandwiches customConfig between default reference // config and default overrides, and then resolves it. val system = ActorSystem("MySystem", ConfigFactory.load(customConf)) ``` ## 从自定义位置读取配置 你可以在代码或使用系统属性中替换或补充`application.conf`。 如果你使用的是`ConfigFactory.load()`(默认情况下 Akka 会这样做),那么可以通过定义`-Dconfig.resource=whatever`、`-Dconfig.file=whatever`或`-Dconfig.url=whatever`来替换`application.conf`。 在用`-Dconfig.resource`和`friends`指定的替换文件中,如果你仍然想使用`application.{conf,json,properties}`,可以使用`include "application"`。在`include "application"`之前指定的设置将被包含的文件覆盖,而在`include "application"`之后指定的设置将覆盖包含的文件。 在代码中,有许多自定义选项。 `ConfigFactory.load()`有几个重载;这些重载允许你指定一些夹在系统属性(重写)和默认值(来自`reference.conf`)之间的内容,替换常规`application.{conf,json,properties}`并替换` -Dconfig.file`和`friends`。 `ConfigFactory.load()`的最简单变体采用资源基名称(`resource basename`),而不是应用程序;然后将使用`myname.conf`、`myname.json`和`myname.properties`而不是`application.{conf,json,properties}`。 最灵活的变体采用`Config`对象,你可以使用`ConfigFactory`中的任何方法加载该对象。例如,你可以使用`ConfigFactory.parseString()`在代码中放置配置字符串,也可以制作映射和`ConfigFactory.parseMap()`,或者加载文件。 你还可以将自定义配置与常规配置结合起来,这可能看起来像: ```java // make a Config with just your special setting Config myConfig = ConfigFactory.parseString("something=somethingElse"); // 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("myname", complete); ``` 使用`Config`对象时,请记住蛋糕中有三个“层”: - `ConfigFactory.defaultOverrides()`(系统属性) - 应用程序的设置 - `ConfigFactory.defaultReference()`(`reference.conf`) 通常的目标是定制中间层,而不让其他两层单独使用。 - `ConfigFactory.load()`加载整个堆栈 - `ConfigFactory.load()`的重载允许你指定不同的中间层 - `ConfigFactory.parse()`变体加载单个文件或资源 要堆叠两层,请使用`override.withFallback(fallback)`;尝试将系统属性(`defaultOverrides()`)保持在顶部,并将`reference.conf`(`defaultReference()`)保持在底部。 请记住,你通常可以在`application.conf`中添加另一个`include`语句,而不是编写代码。`application.conf`顶部的`include`将被`application.conf`的其余部分覆盖,而底部的`include`将覆盖前面的内容。 ## Actor 部署配置 特定 Actor 的部署设置可以在配置的`akka.actor.deployment`部分中定义。在部署部分,可以定义调度程序、邮箱、路由设置和远程部署等内容。这些功能的配置在详细介绍相应主题的章节中进行了描述。示例如下: ``` akka.actor.deployment { # '/user/actorA/actorB' is a remote deployed actor /actorA/actorB { remote = "akka.tcp://sampleActorSystem@127.0.0.1:2553" } # all direct children of '/user/actorC' have a dedicated dispatcher "/actorC/*" { dispatcher = my-dispatcher } # all descendants of '/user/actorC' (direct children, and their children recursively) # have a dedicated dispatcher "/actorC/**" { dispatcher = my-dispatcher } # '/user/actorD/actorE' has a special priority mailbox /actorD/actorE { mailbox = prio-mailbox } # '/user/actorF/actorG/actorH' is a random pool /actorF/actorG/actorH { router = random-pool nr-of-instances = 5 } } my-dispatcher { fork-join-executor.parallelism-min = 10 fork-join-executor.parallelism-max = 10 } prio-mailbox { mailbox-type = "a.b.MyPrioMailbox" } ``` - **注释**:特定 Actor 的部署部分由 Actor 相对于`/user`的路径标识。 可以使用星号作为 Actor 路径部分的通配符匹配,因此可以指定:`/*/sampleActor`,它将匹配层次结构中该级别上的所有`sampleActor`。此外,请注意: - 可以在最后一个位置使用通配符来匹配特定级别的所有 Actor:`/someparent/*` - 可以在最后一个位置使用双通配符以递归方式匹配所有子 Actor 及其子参 Actor:`/someparent/**` - 非通配符匹配总是比通配符具有更高的匹配优先级,并且单个通配符匹配比双通配符具有更高的优先级,因此:`/foo/bar`被认为比`/foo/*`更具体,后者被认为比`/foo/**`更具体,仅使用最高优先级匹配。 - 通配符不能用于部分匹配,如`/foo*/bar`、`/f*o/bar`等。 - 双通配符只能放在最后一个位置。 ## 参考配置列表 每个 Akka 模块都有一个带有默认值的参考配置文件。 - [akka-actor](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-actor) - [akka-agent](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-agent) - [akka-camel](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-camel) - [akka-cluster](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-cluster) - [akka-multi-node-testkit](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-multi-node-testkit) - [akka-persistence](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-persistence) - [akka-remote](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-remote) - [akka-remote (artery)](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-remote-artery-) - [akka-testkit](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-testkit) - [akka-cluster-metrics](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-cluster-metrics) - [akka-cluster-tools](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-cluster-tools) - [akka-cluster-sharding](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-cluster-sharding) - [akka-distributed-data](https://doc.akka.io/docs/akka/current/general/configuration.html#akka-distributed-data) ---------- **英文原文链接**:[Configuration](https://doc.akka.io/docs/akka/current/general/configuration.html). ---------- ———— ☆☆☆ —— [返回 -> Akka 中文指南 <- 目录](https://codechina.csdn.net/monokai/akka-guide/blob/master/README.md) —— ☆☆☆ ————