【问题标题】:What is the best practice to make microservice aware about name of another microservice for interaction使微服务了解另一个微服务的名称以进行交互的最佳实践是什么
【发布时间】:2021-06-11 01:07:03
【问题描述】:

我有几个用 Spring Boot 编写的微服务,它们相互交互以执行某些任务。我需要使用 Kubernetes 在 AWS 中部署这些微服务。为了使微服务相互交互,一个服务需要知道另一个服务的名称。这是我不确定如何继续的地方。

由于我计划使用 Kubernetes 进行部署,我将为这两个微服务创建 Kubernetes 服务,并希望利用 Kubernetes 的 DNS 解析。现在我的问题是如何让一个微服务知道 Kubernetes 服务名称。我能想到的一个选择是,将微服务的名称放在 application.properties 中并创建具有相同名称的 Kubernetes 服务,但使用这种方法,我的印象是我正在计划失败。如果将来我的服务名称需要更改,那么我还需要记住更改依赖于此的每个微服务中的名称。

我认为这是人们在使用 Kubernetes 部署微服务期间可能面临的非常常见的场景。那么,这样做的最佳做法是什么?

【问题讨论】:

    标签: java kubernetes deployment microservices


    【解决方案1】:

    一种解决方案是使用配置映射并在配置映射中添加这些 mirco 服务 URL。然后您可以将它们挂载到部署 pod 模板中并在您的应用程序中使用它们。

    所以以后,如果你需要改变微服务的 URL,你必须相应地改变配置映射。

    如果你想要微服务地址作为环境,那么你的配置映射将是这样的:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: service-config
    data:
      micro_service_1: "value1"
      micro_service_2: "value2"
    
    

    或者你可以在一些属性文件中使用它们:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: service-config
    data:
      service.properties: |
        micro_service_1: "value1"
        micro_service_2: "value2"
    

    然后将它们挂载到您的部署 pod 模板规范中:

    spec:
      containers:
        - name: demo
          image: alpine
          env:
            - name: MICROSERVICE_1
              valueFrom:
                configMapKeyRef:
                  name: service-config
                  key: microservice_1
            - name: MICROSERVICE_2
              valueFrom:
                configMapKeyRef:
                  name: service-config
                  key: microservice_2
          # you will need volumeMounts and volumes if and only if you use service address from properties file. Then you can skip above env part
          volumeMounts:
          - name: config
            mountPath: "/config"
            readOnly: true
      volumes:
        # You set volumes at the Pod level, then mount them into containers inside that Pod
        - name: config
          configMap:
            # Provide the name of the ConfigMap you want to mount.
            name: secret-config
            # An array of keys from the ConfigMap to create as files
            items:
            - key: "service.properties"
              path: "service.properties"
    
    

    【讨论】:

    • 谢谢,但我认为您不一定需要创建一个卷来使用配置映射。是吗?
    • 是的,但是如果您希望文件中的配置进入特定路径而不是 env,那么您将需要一个卷。
    【解决方案2】:

    将服务名称作为环境变量传递。可以直接将这些嵌入到客户端的 YAML 规范中(如果您使用像 Helm 这样的模板工具,这会稍微容易一些),尽管使用间接 ConfigMap 也可以。

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: other-service
    spec:
      ports:
        - port: 80          # make the Service use the standard HTTP port
          targetPort: http  # even if the Pod uses something else
    ...
    ---
    apiVersion: apps/v1
    kind: Deployment
    spec:
      ...
        env:
          - name: OTHERSERVICE_URL
            value: http://other-service
    

    每种语言都有一些检索环境变量的方法(Python os.environ[]、Node process.env、...),因此无论实现语言如何,您都可以使用这种方法。如果未设置环境变量,请将其默认值设为对开发人员有用的值,可能是已知端口上的 localhost URL。

    特别是在 Spring Boot 客户端中,environment variables can be directly used as Spring properties(另请参阅 more specific rules for environment variable names)以便您的 application.yml 文件可以指定

    other-service:
      url: http://localhost:12345
    

    然后您的客户端可以配置为

    @ConfigurationProperties(prefix="other-service")
    @Data
    public class OtherServiceClient {
      private String url;
    }
    

    这里不要尝试使用 Spring 属性文件来配置服务 URL。 (在 Helm 上下文中,您可以在 ConfigMap 中动态构建完整的属性文件,但环境变量方法更通用。)因为 URL 可以具有几乎任何主机名(同样,特别是在 Helm 上下文中,其中的名称通常是构建的)你不想重新编译你的 jar 文件来重新部署到新的地方。

    【讨论】:

      【解决方案3】:

      我不太熟悉 kubernates 以及您可以在多大程度上利用 Kubernetes 的 DNS 解析。但是,如果您使用的是 Spring Boot,您可以利用 Spring Cloud,它提供了一些称为 Service discovery/registry 的解决方案/服务,可用于查找各种微服务,并且您可以使用 feign 客户端进行通信他们之间。

      您需要创建 Eureka(netflix Eureka 是 Spring Cloud 下的宠物项目)服务器,您的客户端服务将在其中注册自己(在您的情况下是不同的不同微服务),您的微服务将成为该服务器的客户端。

      您可以找到 spring.io 文档,该文档将为您提供基本的设置示例。

      这里https://spring.io/guides/gs/service-registration-and-discovery/

      关于这里的声明式 REST 客户端的 feign
      https://cloud.spring.io/spring-cloud-netflix/multi/multi_spring-cloud-feign.html

      【讨论】:

        猜你喜欢
        • 2019-08-16
        • 2018-09-28
        • 1970-01-01
        • 1970-01-01
        • 2019-10-25
        • 2016-09-09
        • 1970-01-01
        • 2019-01-08
        • 1970-01-01
        相关资源
        最近更新 更多