您可以将 Spring Cloud 微服务应用托管到 EDAS,使用 EDAS 提供的共享组件、企业级安全加固和完整的微服务解决方案,帮助您节省运维成本、提升安全性和开发效率。本文将介绍如何在本地开发一个 Spring Cloud 微服务示例应用(包含一个服务提供者 Provider 和一个服务消费者 Consumer)并部署到 EDAS。

背景信息

  • 如果您完全不了解 Spring Cloud,只有简单的 Spring 和 Maven 基础,详细阅读本文后,您将了解如何通过 Spring Cloud Alibaba Nacos Discovery 实现 Spring Cloud 应用的服务注册与发现,以及实现消费者对提供者的调用。
  • 如果您熟悉 Spring Cloud 中的服务注册组件(如 Eureka、Consul 和 ZooKeeper),但尚未使用过 Spring Cloud Alibaba 的服务注册组件 Nacos Discovery,那么您只需要将这些服务注册组件的依赖和配置替换成 Spring Cloud Alibaba Nacos Discovery,无需修改任何代码。

    Spring Cloud Alibaba Nacos Discovery 同样实现了 Spring Cloud Registry 的标准接口与规范,和您之前使用 Spring Cloud 接入服务注册与发现的方式基本一致。

  • 如果您熟悉如何使用开源版本的 Spring Cloud Alibaba Nacos Discovery 实现 Spring Cloud 应用的服务注册与发现,那么您可以将应用直接部署到 EDAS(详情请参见应用部署概述(ECS 集群)应用部署概述(K8s 集群)),即可使用到 EDAS 提供的商业版服务注册与发现的能力。

EDAS 服务注册中心提供了开源 Nacos Server 的商用版本,使用开源版本 Spring Cloud Alibaba Nacos Discovery开发的应用可以直接使用 EDAS 提供的商业版服务注册中心。

商业版的 EDAS 服务注册中心与 Nacos、Eureka 和 Consul 相比,具有以下优势:

  • 共享组件,节省了部署、运维 Nacos、Eureka 或 Consul 的成本。
  • 在服务注册和发现的调用中都进行了链路加密,保护您的服务,无需再担心服务被未授权的应用发现。
  • EDAS 服务注册中心与 EDAS 其他组件紧密结合,为您提供一整套的微服务解决方案,包括环境隔离、平滑上下线、灰度发布等。

准备工作

本地开发中主要描述开发中涉及的关键信息,如果您想了解完整的 Spring Cloud 应用程序,可下载 service-providerservice-consumer

在开始开发前,请确保您已经完成以下工作:

  • 下载 Maven 并设置环境变量。
  • 下载最新版本的 Nacos Server
  • 按以下步骤启动 Nacos Server。
    1. 解压下载的 Nacos Server 压缩包
    2. 进入nacos/bin目录,启动 Nacos Server。
      • Linux/Unix/Mac 系统:执行命令sh startup.sh -m standalone
      • Windows 系统:双击执行startup.cmd文件。
    3. 在本地开发应用时,可以使用 Alibaba Cloud Toolkit 插件实现本地应用和部署在 EDAS 中的应用的相互调用,即端云互联,而无需搭建 VPN,帮助您提升开发效率。详情请参见为 EDAS 应用设置端云互联

创建服务提供者

在本地创建服务提供者应用工程,添加依赖,开启服务注册与发现功能,并将注册中心指定为 Nacos Server。

  1. 创建命名为nacos-service-provider的 Maven 工程。
  2. pom.xml 文件中添加依赖。

    以 Spring Boot 2.1.4.RELEASE 和 Spring Cloud Greenwich.SR1 为例,依赖如下:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>                  

    示例中使用的版本为 Spring Cloud Greenwich ,对应 Spring Cloud Alibaba 版本为 2.1.1.RELEASE。

    • 如果使用 Spring Cloud Finchley 版本,对应 Spring Cloud Alibaba 版本为 2.0.1.RELEASE。
    • 如果使用 Spring Cloud Edgware 版本,对应 Spring Cloud Alibaba 版本为 1.5.1.RELEASE。
    说明 Spring Cloud Edgware 版本的生命周期已结束,不推荐使用这个版本开发应用。
  3. src\main\java下创建 Packagecom.aliware.edas
  4. 在 Packagecom.aliware.edas中创建服务提供者的启动类ProviderApplication,并添加如下代码。

    其中@EnableDiscoveryClient注解表明此应用需开启服务注册与发现功能。

        package com.aliware.edas;
    
        import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
        @SpringBootApplication
        @EnableDiscoveryClient
        public class ProviderApplication {
    
            public static void main(String[] args) {
                SpringApplication.run(ProviderApplication.class, args);
            }
        }             
  5. 在 Packagecom.aliware.edas中创建EchoController,指定 URL mapping 为 {/echo/{String}},指定 HTTP 方法为 GET,方法参数从 URL 路径中获得,回显收到的参数。
        package com.aliware.edas;
    
        import org.springframework.web.bind.annotation.PathVariable;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RequestMethod;
        import org.springframework.web.bind.annotation.RestController;
    
        @RestController
        public class EchoController {
            @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
            public String echo(@PathVariable String string) {
                return string;
            }
        }              
  6. src\main\resources路径下创建文件application.properties,在application.properties中添加如下配置,指定 Nacos Server 的地址。

    其中127.0.0.1为 Nacos Server 的地址。如果您的 Nacos Server 部署在另外一台机器,则需要修改成对应的 IP 地址。如果有其它需求,可以参考配置项参考application.properties文件中增加配置。

        spring.application.name=service-provider
        server.port=18081
        spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848               
  7. 验证结果。
    1. 执行nacos-service-providerProviderApplicationmain函数,启动应用。
    2. 登录本地启动的 Nacos Server 控制台http://127.0.0.1:8848/nacos(本地 Nacos 控制台的默认用户名和密码同为 nacos)。
    3. 在左侧导航栏中选择服务管理 > 服务列表
      可以看到服务列表中已经包含了service-provider,且在详情中可以查询该服务的详情。

创建服务消费者

本内容除介绍服务注册的功能,还将介绍 Nacos 服务发现与 RestTemplate 和 FeignClient 两个客户端如何配合使用。

  1. 创建命名为nacos-service-consumer的 Maven 工程。
  2. pom.xml中添加依赖。
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
        <relativePath/>
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <version>2.1.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>        
  3. src\main\java下创建 Packagecom.aliware.edas
  4. 在 Packagecom.aliware.edas中配置 RestTemplate 和 FeignClient。
    1. 在 Packagecom.aliware.edas 中创建一个接口类EchoService,添加@FeignClient注解,并配置对应的 HTTP URL 地址及 HTTP 方法。
      package com.aliware.edas;
      
      import org.springframework.cloud.openfeign.FeignClient;
      import org.springframework.web.bind.annotation.PathVariable;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestMethod;
      
      @FeignClient(name = "service-provider")
      public interface EchoService {
          @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
          String echo(@PathVariable("str") String str);
      }                   
    2. 在 Packagecom.aliware.edas 中创建启动类ConsumerApplication并添加相关配置。
      • 使用@EnableDiscoveryClient注解启用服务注册与发现。
      • 使用@EnableFeignClients注解激活 FeignClient。
      • 添加@LoadBalanced注解将 RestTemplate 与服务发现集成。
      package com.aliware.edas;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      import org.springframework.cloud.client.loadbalancer.LoadBalanced;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      import org.springframework.context.annotation.Bean;
      import org.springframework.web.client.RestTemplate;
      
      @SpringBootApplication
      @EnableDiscoveryClient
      @EnableFeignClients
      public class ConsumerApplication {
      
          @LoadBalanced
          @Bean
          public RestTemplate restTemplate() {
              return new RestTemplate();
          }
      
          public static void main(String[] args) {
              SpringApplication.run(ConsumerApplication.class, args);
          }
      }
  5. 在 Packagecom.aliware.edas 中创建类TestController以演示和验证服务发现功能。
        package com.aliware.edas;
    
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.web.bind.annotation.PathVariable;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RequestMethod;
        import org.springframework.web.bind.annotation.RestController;
        import org.springframework.web.client.RestTemplate;
    
        @RestController
        public class TestController {
    
            @Autowired
            private RestTemplate restTemplate;
            @Autowired
            private EchoService echoService;
    
            @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
            public String rest(@PathVariable String str) {
                return restTemplate.getForObject("http://service-provider/echo/" + str,
                        String.class);
            }
    
            @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
            public String feign(@PathVariable String str) {
                return echoService.echo(str);
            }
    
        }           
  6. src\main\resources路径下创建文件application.properties,在application.properties中添加如下配置,指定 Nacos Server 的地址。

    其中127.0.0.1:8848为 Nacos Server 的地址。如果您的 Nacos Server 部署在另外一台机器,则需要修改成对应的地址。如果有其它需求,可以参考配置项参考application.properties文件中增加配置。

        spring.application.name=service-consumer
        server.port=18082
        spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
  7. 验证结果。
    1. 执行nacos-service-consumerConsumerApplicationmain 函数,启动应用。
    2. 登录本地启动的 Nacos Server 控制台 http://127.0.0.1:8848/nacos(本地 Nacos 控制台的默认用户名和密码同为 nacos)。
    3. 在左侧导航栏中选择服务管理 > 服务列表,可以看到服务列表中已经包含了service-consumer,且在详情中可以查询该服务的详情。

本地测试

在本地测试消费者对提供者的服务调用结果。

  • Linux/Unix/Mac 系统:运行以下命令。
    curl http://127.0.0.1:18082/echo-rest/rest-rest
    curl http://127.0.0.1:18082/echo-feign/feign-rest
  • Windows系统:在浏览器中输入 http://127.0.0.1:18082/echo-rest/rest-resthttp://127.0.0.1:18082/echo-feign/feign-rest

将应用部署到 EDAS

当在本地完成应用的开发和测试后,便可将应用程序打包并部署到 EDAS。您可以根据您的实际情况选择将 Spring Cloud 应用可以部署到 ECS 集群、容器服务 Kubernetes集群或 EDAS Serverless。部署应用的详细步骤请参见应用部署概述(ECS 集群)应用部署概述(K8s 集群)

说明 第一次部署建议通过控制台部署,且如果使用 JAR 包部署,在创建应用时应用运行环境务必选择标准 Java 应用运行环境
EDAS应用部署方式

EDAS 服务注册中心提供了商用版本 Nacos Server。当您将应用部署到 EDAS 的时候,EDAS 会通过优先级更高的方式去设置 Nacos Server 服务端地址和服务端口,以及 namespace、access-key、secret-key、context-path 信息。您无需进行任何额外的配置,原有的配置内容可以选择保留或删除。

结果验证

在部署完成之后,在 EDAS 控制台左侧导航栏选择微服务管理 > 服务查询,在服务查询页面选择地域命名空间,然后通过搜索service-providerservice-consumer查询您部署的应用。

配置项参考

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.discovery.server-addr Nacos Server 启动监听的 IP 地址和端口。
服务名 spring.cloud.nacos.discovery.service ${spring.application.name} 给当前的服务命名。
网卡名 spring.cloud.nacos.discovery.network-interface 当 IP 未配置时,注册的 IP 为此网卡所对应的 IP 地址。如果此项也未配置,则默认取第一块网卡的地址。
注册的 IP 地址 spring.cloud.nacos.discovery.ip 优先级最高
注册的端口 spring.cloud.nacos.discovery.port -1 默认情况下不用配置,系统会自动探测。
命名空间 spring.cloud.nacos.discovery.namespace 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
Metadata spring.cloud.nacos.discovery.metadata 使用 Map 格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息。
集群 spring.cloud.nacos.discovery.cluster-name DEFAULT 配置成 Nacos 集群名称。
接入点 spring.cloud.nacos.discovery.enpoint UTF-8 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址,此配置在部署到 EDAS 时无需填写。
是否集成 Ribbon ribbon.nacos.enabled true 一般不需要修改

更多关于 Spring Cloud Alibaba Nacos Discovery 的信息请参见开源版本的 Spring Cloud Alibaba Nacos Discovery 文档

常见问题

示例中使用的 Spring Cloud 版本为 Greenwich,对应的 Spring Cloud Alibaba 版本为 2.1.1.RELEASE。Spring Cloud Finchley 对应的 Spring Cloud Alibaba 版本为 2.0.1.RELEASE,Spring Cloud Edgware 对应的 Spring Cloud Alibaba 版本为 1.5.1.RELEASE。

说明 Spring Cloud Edgware 版本的生命周期已结束,不推荐使用这个版本开发应用。