阅读(409) (0)

Micronaut 服务发现

2023-02-23 13:41:43 更新

服务发现使微服务能够在不知道相关服务的物理位置或 IP 地址的情况下找到彼此。

Micronaut 集成了多种工具和库。有关详细信息,请参阅 Micronaut 服务发现文档

Consul 支持

请参阅 Micronaut Consul 文档。

Eureka 支持

请参阅 Micronaut Eureka 文档。

Kubernetes 支持

Kubernetes 是一个容器运行时,具有许多功能,包括集成服务发现和分布式配置。

Micronaut 包括与 Kubernetes 的一流集成。有关详细信息,请参阅 Micronaut Kubernetes 文档。

AWS Route 53 支持

要使用 Route 53 Service Discovery,您必须满足以下条件:

  • 运行某种类型的 EC2 实例

  • 在 Route 53 中托管域名

  • 拥有较新版本的 AWS-CLI(例如 14+)

假设你有这些东西,你就准备好了。它不像 Consul 或 Eureka 那样花哨,但除了使用 AWS-CLI 进行一些初始设置外,没有其他软件运行出错。如果您向服务添加自定义健康检查,您甚至可以支持健康检查。如需更多信息,请访问 https://docs.aws.amazon.com/Route53/latest/APIReference/overview-service-discovery.html

以下是步骤:

  1. 使用 AWS-CLI 创建命名空间。您可以根据您使用的 IP 或子网创建公共或私有的

  2. 使用 AWS-CLI 命令创建具有 DNS 记录的服务

  3. 添加健康检查或自定义健康检查(可选)

  4. 将服务 ID 添加到您的应用程序配置文件中,如下所示:

示例应用程序配置

 Properties Yaml  Toml  Groovy  Hocon  JSON 
aws.route53.registration.enabled=true
aws.route53.registration.aws-service-id=srv-978fs98fsdf
aws.route53.registration.namespace=micronaut.io
micronaut.application.name=something
aws:
  route53:
    registration:
        enabled: true
        aws-service-id: srv-978fs98fsdf
        namespace: micronaut.io
micronaut:
  application:
    name: something
[aws]
  [aws.route53]
    [aws.route53.registration]
      enabled=true
      aws-service-id="srv-978fs98fsdf"
      namespace="micronaut.io"
[micronaut]
  [micronaut.application]
    name="something"
aws {
  route53 {
    registration {
      enabled = true
      awsServiceId = "srv-978fs98fsdf"
      namespace = "micronaut.io"
    }
  }
}
micronaut {
  application {
    name = "something"
  }
}
{
  aws {
    route53 {
      registration {
        enabled = true
        aws-service-id = "srv-978fs98fsdf"
        namespace = "micronaut.io"
      }
    }
  }
  micronaut {
    application {
      name = "something"
    }
  }
}
{
  "aws": {
    "route53": {
      "registration": {
        "enabled": true,
        "aws-service-id": "srv-978fs98fsdf",
        "namespace": "micronaut.io"
      }
    }
  },
  "micronaut": {
    "application": {
      "name": "something"
    }
  }
}
  1. 确保您的构建文件中具有以下依赖项:

 Gradle Maven 
implementation("io.micronaut.aws:micronaut-aws-route53")
<dependency>
    <groupId>io.micronaut.aws</groupId>
    <artifactId>micronaut-aws-route53</artifactId>
</dependency>
  1. 在客户端,您需要相同的依赖项和更少的配置选项:

 Properties Yaml  Toml  Groovy  Hocon  JSON 
aws.route53.discovery.client.enabled=true
aws.route53.discovery.client.aws-service-id=srv-978fs98fsdf
aws.route53.discovery.client.namespace-id=micronaut.io
aws:
  route53:
    discovery:
      client:
        enabled: true
        aws-service-id: srv-978fs98fsdf
        namespace-id: micronaut.io
[aws]
  [aws.route53]
    [aws.route53.discovery]
      [aws.route53.discovery.client]
        enabled=true
        aws-service-id="srv-978fs98fsdf"
        namespace-id="micronaut.io"
aws {
  route53 {
    discovery {
      client {
        enabled = true
        awsServiceId = "srv-978fs98fsdf"
        namespaceId = "micronaut.io"
      }
    }
  }
}
{
  aws {
    route53 {
      discovery {
        client {
          enabled = true
          aws-service-id = "srv-978fs98fsdf"
          namespace-id = "micronaut.io"
        }
      }
    }
  }
}
{
  "aws": {
    "route53": {
      "discovery": {
        "client": {
          "enabled": true,
          "aws-service-id": "srv-978fs98fsdf",
          "namespace-id": "micronaut.io"
        }
      }
    }
  }
}

然后,您可以使用 DiscoveryClient API 查找通过 Route 53 注册的其他服务。例如:

Sample code for client

DiscoveryClient discoveryClient = embeddedServer.getApplicationContext().getBean(DiscoveryClient.class);
List<String> serviceIds = Flux.from(discoveryClient.getServiceIds()).blockFirst();
List<ServiceInstance> instances = Flux.from(discoveryClient.getInstances(serviceIds.get(0))).blockFirst();

创建命名空间

命名空间类似于常规的 Route53 托管区域,它们出现在 Route53 控制台中,但控制台不支持修改它们。您此时必须使用 AWS-CLI 来实现任何服务发现功能。

首先决定你是创建面向公众的命名空间还是私有命名空间,因为命令不同:

Creating Namespace

$ aws servicediscovery create-public-dns-namespace --name micronaut.io --create-request-id create-1522767790 --description adescriptionhere

or

$ aws servicediscovery create-private-dns-namespace --name micronaut.internal.io --create-request-id create-1522767790 --description adescriptionhere --vpc yourvpcID

当您运行它时,您将获得一个操作 ID。您可以使用 get-operation CLI 命令检查状态:

Get Operation Results

$ aws servicediscovery get-operation --operation-id asdffasdfsda

您可以使用此命令获取您进行的任何返回操作 ID 的调用的状态。

命令的结果将告诉您命名空间的 ID。把它写下来,你会在接下来的步骤中需要它。如果您遇到错误,它会说明错误是什么。

创建服务和 DNS 记录

下一步是创建服务和 DNS 记录。

Create Service

$ aws create-service --name yourservicename --create-request-id somenumber --description someservicedescription --dns-config NamespaceId=yournamespaceid,RoutingPolicy=WEIGHTED,DnsRecords=[{Type=A,TTL=1000},{Type=A,TTL=1000}]

DnsRecord 类型可以是 A(ipv4)、AAAA(ipv6)、SRV 或 CNAME。 RoutingPolicy 可以是 WEIGHTED 或 MULTIVALUE。请记住 CNAME 必须使用加权路由类型,SRV 必须配置有效端口。

要添加运行状况检查,请在 CLI 上使用以下语法:

Specifying a Health Check

Type=string,ResourcePath=string,FailureThreshold=integer

类型可以是“HTTP”、“HTTPS”或“TCP”。您只能对公共命名空间使用标准健康检查。请参阅私有命名空间的自定义健康检查。资源路径应该是一个 URL,如果正常则返回 200 OK。

对于自定义健康检查,您只需指定 --health-check-custom-config FailureThreshold=integer ,它也适用于私有命名空间。

这也很好,因为 Micronaut 发出脉动命令让 AWS 知道实例仍然健康。

如需更多帮助,请运行“aws discoveryservice create-service help”。

如果成功,您将从该命令返回一个服务 ID 和一个 ARN。记下来,它将进入 Micronaut 配置。

在 Micronaut 中设置配置

自动命名注册

添加配置以使您的应用程序注册到 Route 53 自动发现:

Registration Properties

 Properties Yaml  Toml  Groovy  Hocon  JSON 
aws.route53.registration.enabled=true
aws.route53.registration.aws-service-id=<enter the service id you got after creation on aws cli>
aws.route53.discovery.namespace-id=<enter the namespace id you got after creating the namespace>
aws:
  route53:
    registration:
      enabled: true
      aws-service-id: <enter the service id you got after creation on aws cli>
    discovery:
      namespace-id: <enter the namespace id you got after creating the namespace>
[aws]
  [aws.route53]
    [aws.route53.registration]
      enabled=true
      aws-service-id="<enter the service id you got after creation on aws cli>"
    [aws.route53.discovery]
      namespace-id="<enter the namespace id you got after creating the namespace>"
aws {
  route53 {
    registration {
      enabled = true
      awsServiceId = "<enter the service id you got after creation on aws cli>"
    }
    discovery {
      namespaceId = "<enter the namespace id you got after creating the namespace>"
    }
  }
}
{
  aws {
    route53 {
      registration {
        enabled = true
        aws-service-id = "<enter the service id you got after creation on aws cli>"
      }
      discovery {
        namespace-id = "<enter the namespace id you got after creating the namespace>"
      }
    }
  }
}
{
  "aws": {
    "route53": {
      "registration": {
        "enabled": true,
        "aws-service-id": "<enter the service id you got after creation on aws cli>"
      },
      "discovery": {
        "namespace-id": "<enter the namespace id you got after creating the namespace>"
      }
    }
  }
}

发现客户端配置

Discovery Properties

 Properties Yaml  Toml  Groovy  Hocon  JSON 
aws.route53.discovery.client.enabled=true
aws.route53.discovery.client.aws-service-id=<enter the service id you got after creation on aws cli>
aws:
  route53:
    discovery:
      client:
        enabled: true
        aws-service-id: <enter the service id you got after creation on aws cli>
[aws]
  [aws.route53]
    [aws.route53.discovery]
      [aws.route53.discovery.client]
        enabled=true
        aws-service-id="<enter the service id you got after creation on aws cli>"
aws {
  route53 {
    discovery {
      client {
        enabled = true
        awsServiceId = "<enter the service id you got after creation on aws cli>"
      }
    }
  }
}
{
  aws {
    route53 {
      discovery {
        client {
          enabled = true
          aws-service-id = "<enter the service id you got after creation on aws cli>"
        }
      }
    }
  }
}
{
  "aws": {
    "route53": {
      "discovery": {
        "client": {
          "enabled": true,
          "aws-service-id": "<enter the service id you got after creation on aws cli>"
        }
      }
    }
  }
}

您还可以通过获取 bean“Route53AutoNamingClient”来调用以下方法:

Discovery Methods

// if serviceId is null it will use property "aws.route53.discovery.client.awsServiceId"
Publisher<List<ServiceInstance>> getInstances(String serviceId)
// reads property "aws.route53.discovery.namespaceId"
Publisher<List<String>> getServiceIds()

集成测试

如果您设置环境变量 AWS_SUBNET_ID 并在您的主目录中配置有效的凭证(在 ~/.aws/credentials 中),您可以运行集成测试。您还需要一个托管在 Route53 上的域。此测试将创建一个 t2.nano 实例、一个命名空间、服务,并将该实例注册到服务发现。当测试完成时,它将删除/终止它启动的所有资源。

手动服务发现配置

如果您不希望涉及像 Consul 这样的服务发现服务器,或者您与无法向 Consul 注册的第三方服务交互,您可以手动配置通过服务发现可用的服务。

为此,请使用 micronaut.http.services 设置。例如:

Manually configuring services

 Properties Yaml  Toml Groovy  Hocon  JSON 
micronaut.http.services.foo.urls[0]=http://foo1
micronaut.http.services.foo.urls[1]=http://foo2
micronaut:
  http:
    services:
      foo:
        urls:
          - http://foo1
          - http://foo2
[micronaut]
  [micronaut.http]
    [micronaut.http.services]
      [micronaut.http.services.foo]
        urls=[
          "http://foo1",
          "http://foo2"
        ]
micronaut {
  http {
    services {
      foo {
        urls = ["http://foo1", "http://foo2"]
      }
    }
  }
}
{
  micronaut {
    http {
      services {
        foo {
          urls = ["http://foo1", "http://foo2"]
        }
      }
    }
  }
}
{
  "micronaut": {
    "http": {
      "services": {
        "foo": {
          "urls": ["http://foo1", "http://foo2"]
        }
      }
    }
  }
}

然后,您可以使用 @Client("foo") 注入一个客户端,它将使用上述配置在两个配置的服务器之间进行负载平衡。

将@Client 与服务发现一起使用时,必须在 kebab-case 的注释中指定服务 ID。然而,上述示例中的配置可以采用驼峰式大小写。

您可以通过指定环境变量(例如 MICRONAUT_HTTP_SERVICES_FOO_URLS=http://prod1,http://prod2)在生产环境中覆盖此配置

请注意,默认情况下不会进行健康检查来断言引用的服务是可操作的。您可以通过启用健康检查并选择性地指定健康检查路径(默认为 /health)来改变它:

Enabling Health Checking

 Properties Yaml  Toml  Groovy  Hocon  JSON 
micronaut.http.services.foo.health-check=true
micronaut.http.services.foo.health-check-interval=15s
micronaut.http.services.foo.health-check-uri=/health
micronaut:
  http:
    services:
      foo:
        health-check: true
        health-check-interval: 15s
        health-check-uri: /health
[micronaut]
  [micronaut.http]
    [micronaut.http.services]
      [micronaut.http.services.foo]
        health-check=true
        health-check-interval="15s"
        health-check-uri="/health"
micronaut {
  http {
    services {
      foo {
        healthCheck = true
        healthCheckInterval = "15s"
        healthCheckUri = "/health"
      }
    }
  }
}
{
  micronaut {
    http {
      services {
        foo {
          health-check = true
          health-check-interval = "15s"
          health-check-uri = "/health"
        }
      }
    }
  }
}
{
  "micronaut": {
    "http": {
      "services": {
        "foo": {
          "health-check": true,
          "health-check-interval": "15s",
          "health-check-uri": "/health"
        }
      }
    }
  }
}
  • health-check表示是否对该服务进行健康检查

  • health-check-interval 是检查之间的间隔

  • health-check-uri 指定健康检查请求的端点URI

Micronaut 启动一个后台线程来检查服务的健康状态,如果任何配置的服务以错误代码响应,它们就会从可用服务列表中删除。