发现
Akka 发现(Discovery
)提供了一个围绕各种定位服务方式的接口。内置方法有:
- DNS
- 配置
- 聚合
此外,「Akka Management」包括以下方法:
- Kubernetes API
- AWS
- Consul
- Marathon API
Discovery
曾是 Akka 管理的一部分,但从 Akka 的2.5.19
版和 Akka 管理的1.0.0
版开始,它已成为 Akka 的模块。如果你还将 Akka 管理用于其他服务发现方法或加载程序,请确保你至少使用了 Akka 管理(Management
)的1.0.0
版本。
依赖
为了使用 Akka 发现,你需要将以下依赖添加到你的项目中:
<!-- Maven -->
<dependency>
<groupId>com.typesafe.akka</groupId>
<artifactId>akka-discovery_2.12</artifactId>
<version>2.5.22</version>
</dependency>
<!-- Gradle -->
dependencies {
compile group: 'com.typesafe.akka', name: 'akka-discovery_2.12', version: '2.5.22'
}
<!-- sbt -->
libraryDependencies += "com.typesafe.akka" %% "akka-discovery" % "2.5.22"
它是如何工作的?
加载扩展:
ActorSystem as = ActorSystem.create();
ServiceDiscovery serviceDiscovery = Discovery.get(as).discovery();
Lookup
包含一个必需的serviceName
和一个可选的portName
和protocol
。如何解释这些内容取决于发现方法,例如,如果缺少任何字段,DNS 会执行 A/AAAA 记录查询,并执行 SRV 查询以进行完整查找:
serviceDiscovery.lookup(Lookup.create("akka.io"), Duration.ofSeconds(1));
// convenience for a Lookup with only a serviceName
serviceDiscovery.lookup("akka.io", Duration.ofSeconds(1));
portName
和protocol
是可选的,其含义由方法解释。
CompletionStage<ServiceDiscovery.Resolved> lookup =
serviceDiscovery.lookup(
Lookup.create("akka.io").withPortName("remoting").withProtocol("tcp"),
Duration.ofSeconds(1));
当服务打开多个端口(如 HTTP 端口和 Akka 远程处理端口)时,可以使用port
。
发现方法:DNS
DNS 发现映射Lookup
查询如下:
serviceName
、portName
和protocol
:SRV 查询,格式为_port._protocol._name
,其中_
是需要添加的名称。- 任何缺少任何字段的查询都将映射到
serviceName
的 A/AAAA 查询。
Akka 服务发现术语和 SRV 术语之间的映射:
SRV service = port
SRV name = serviceName
SRV protocol = protocol
在application.conf
中将akka-dns
配置为发现的实现:
akka {
discovery {
method = akka-dns
}
}
从那时起,你就可以使用通用 API 来隐藏调用以下方法所使用的发现方法的事实:
import akka.discovery.ServiceDiscovery;
ActorSystem system = ActorSystem.create("Example");
// ...
SimpleServiceDiscovery discovery = ServiceDiscovery.get(system).discovery();
Future<SimpleServiceDiscovery.Resolved> result = discovery.lookup("service-name", Duration.create("500 millis"));
它是如何工作的?
根据发出的是Simple
查找还是Full
查找,DNS 发现将使用 A/AAAA 记录或 SRV 记录。SRV 记录的优点是它们可以包含一个端口。
SRV 记录
设置了所有字段的查找将成为 SRV 查询。例如:
dig srv _service._tcp.akka.test
; <<>> DiG 9.11.3-RedHat-9.11.3-6.fc28 <<>> srv service.tcp.akka.test
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 60023
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 5
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 5ab8dd4622e632f6190f54de5b28bb8fb1b930a5333c3862 (good)
;; QUESTION SECTION:
;service.tcp.akka.test. IN SRV
;; ANSWER SECTION:
_service._tcp.akka.test. 86400 IN SRV 10 60 5060 a-single.akka.test.
_service._tcp.akka.test. 86400 IN SRV 10 40 5070 a-double.akka.test.
在这种情况下,service.tcp.akka.test
解析为端口5060
上的a-double.akka.test
和端口5070
上的a-double.akka.test
。当前发现不支持权重。
A/AAAA 记录
缺少任何字段的查找将成为 A/AAAA 记录查询。例如:
dig a-double.akka.test
; <<>> DiG 9.11.3-RedHat-9.11.3-6.fc28 <<>> a-double.akka.test
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 11983
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 1, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
; COOKIE: 16e9815d9ca2514d2f3879265b28bad05ff7b4a82721edd0 (good)
;; QUESTION SECTION:
;a-double.akka.test. IN A
;; ANSWER SECTION:
a-double.akka.test. 86400 IN A 192.168.1.21
a-double.akka.test. 86400 IN A 192.168.1.22
在这种情况下,a-double.akka.test
将解析为192.168.1.21
和192.168.1.22
。
发现方法:配置
配置(Configuration
)当前忽略服务名称以外的所有字段。
对于简单的用例,可以使用配置来发现服务。将 Akka Discovery 与配置一起使用而不是与你自己的配置值一起使用的好处是,可以将应用程序迁移到更复杂的发现方法,而无需更改任何代码。
在application.conf
中将其配置为发现方法:
akka {
discovery.method = config
}
默认情况下,可发现的服务在akka.discovery.config.services
中定义,格式如下:
akka.discovery.config.services = {
service1 = {
endpoints = [
{
host = "cat"
port = 1233
},
{
host = "dog"
port = 1234
}
]
},
service2 = {
endpoints = []
}
}
上面的块定义了两个服务,service1
和service2
。每个服务可以有多个endpoints
。
发现方法:聚合多个发现方法
聚合(Aggregate
)发现允许聚合多个发现方法,例如,尝试通过 DNS 解析并返回到配置。
若要使用聚合发现,请添加其依赖项以及要聚合的所有发现。
将aggregate
配置为akka.discovery.method
,并尝试使用哪些发现方法,以及按何种顺序执行。
akka {
discovery {
method = aggregate
aggregate {
discovery-methods = ["akka-dns", "config"]
}
config {
services {
service1 {
endpoints [
{
host = "host1"
port = 1233
},
{
host = "host2"
port = 1234
}
]
}
}
}
}
}
上述配置将导致首先检查akka-dns
,如果它失败或没有返回给定服务名称的目标,那么将查询config
,如上配置了一个名为service1
的服务,其中两个主机为host1
和host2
。
从 Akka Management Discovery 迁移
Akka Discovery 与旧版本的 Akka Management Discovery 不兼容。如果还使用 Akka Discovery,则应至少使用任何 Akka Management 模块的1.0.0
版本。
迁移步骤:
- 任何自定义发现方法现在都应实现
akka.discovery.ServiceDiscovery
discovery-method
现在必须是akka.discovery
下的一个配置位置,至少要有一个属性class
,指定akka.discovery.ServiceDiscovery
实现的完全限定名。以前的版本允许它是类名或完全限定的配置位置,例如akka.discovery.kubernetes-api
,而不仅仅是kubernetes-api
。
英文原文链接:Discovery.