全部产品
阿里云办公

Spring Cloud 接入服务注册与发现

更新时间:2018-09-28 00:30:56

本文介绍如何使用 ANS(Application Naming Service,服务发现组件)将基于 Spring Cloud 开发的应用接入到 EDAS,并实现服务发现。

前提条件

创建服务提供者

  1. 创建一个 Spring Cloud 工程,命名为 service-provider。这里我们以 Spring Boot 1.5.8 和 Spring Cloud Dalston.SR4 为例,在 pom.xml 中引入需要的依赖内容。

    其他版本如 Spring Boot 2 和 Spring Cloud Finchley 也同样支持,请您自行修改版本号和替换相应的组件依赖。

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>1.5.8.RELEASE</version>
    5. <relativePath/>
    6. </parent>
    7. <dependencies>
    8. <dependency>
    9. <groupId>com.alibaba.cloud</groupId>
    10. <artifactId>spring-cloud-starter-ans</artifactId>
    11. <version>1.1.3</version>
    12. </dependency>
    13. <dependency>
    14. <groupId>com.alibaba.cloud</groupId>
    15. <artifactId>spring-cloud-alibaba-edas-starter</artifactId>
    16. <version>1.1.3</version>
    17. </dependency>
    18. </dependencies>
    19. <dependencyManagement>
    20. <dependencies>
    21. <dependency>
    22. <groupId>org.springframework.cloud</groupId>
    23. <artifactId>spring-cloud-dependencies</artifactId>
    24. <version>Dalston.SR4</version>
    25. <type>pom</type>
    26. <scope>import</scope>
    27. </dependency>
    28. </dependencies>
    29. </dependencyManagement>
  2. 编码服务提供端的启动类,其中 @EnableDiscoveryClient 注解表明此应用需开启服务注册与发现功能。

    1. @SpringBootApplication
    2. @EnableDiscoveryClient
    3. public class ServerApplication {
    4. public static void main(String[] args) {
    5. SpringApplication.run(ServerApplication.class, args);
    6. }
    7. }
  3. 创建一个简单的 controller,指定 url mapping 为 {/echo/{String}},指定 http 方法为 GET,方法参数从 url 路径中获得,逻辑是将收到的参数回显。

    1. @RestController
    2. public class EchoController {
    3. @RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
    4. public String echo(@PathVariable String string) {
    5. return string;
    6. }
    7. }
  4. 权限配置,配置阿里云账号的 AccessKey、SecretKey,以及 EDAS 的命名空间信息。

    1. 配置阿里云 AccessKey 和 SecretKey。

      1. 登录阿里云 AK 管理控制台

      2. 在左侧导航栏单击安全信息管理

      3. 安全信息管理页面复制 AccessKey ID 和 Access Key Secret,分别对应配置项中的 alibaba.cloud.access-key 和 alibaba.cloud.secret-key。

        安全凭证信息格式如下:

        1. alibaba.cloud.access-key=xxxxxxxxxx
        2. alibaba.cloud.secret-key=xxxxxxxxxx
      4. 将安全凭证信息粘贴到您的配置文件中,如 application.properties。
    2. 配置 EDAS 的命名空间。

      1. 登录 EDAS 控制台

      2. 在左侧导航栏中单击命名空间

      3. 在命名空间列表页面选择地域,并找到您想发布到的命名空间,复制其命名空间 ID,对应配置项中的 alibaba.edas.namespace

        1. alibaba.edas.namespace=xxxxxxxxxx
      4. 将命名空间信息粘贴到您的配置文件中,如 application.properties。

    3. 经过如上配置之后,我们的配置文件 application.properties 内容如下。

      1. spring.application.name=service-provider
      2. server.port=18081
      3. alibaba.cloud.access-key=xxxxxxxxxx
      4. alibaba.cloud.secret-key=xxxxxxxxxx
      5. alibaba.edas.namespace=cn-hangzhou
  5. 登录 EDAS 控制台,进入服务管理 > 服务查询页面。选择地域命名空间,在服务查询页面查看服务注册的信息。可以在服务名列表查看到创建的服务实例 service-provider,单击详情进入服务详情页,可以查看本机的IP地址和端口等信息。

创建服务消费者

该部分文档我们不仅演示了服务发现的功能,还说明了 ANS 服务发现与 RestTemplate、AsyncRestTemplate 和 FeignClient 这三个客户端是如何结合的。

  1. 创建一个 Spring Cloud 工程,命名为 service-consumer。在 pom.xml 中引入需要的依赖内容:

    1. <parent>
    2. <groupId>org.springframework.boot</groupId>
    3. <artifactId>spring-boot-starter-parent</artifactId>
    4. <version>1.5.8.RELEASE</version>
    5. <relativePath/>
    6. </parent>
    7. <dependencies>
    8. <dependency>
    9. <groupId>com.alibaba.cloud</groupId>
    10. <artifactId>spring-cloud-starter-ans</artifactId>
    11. <version>1.1.3</version>
    12. </dependency>
    13. <dependency>
    14. <groupId>com.alibaba.cloud</groupId>
    15. <artifactId>spring-cloud-alibaba-edas-starter</artifactId>
    16. <version>1.1.3</version>
    17. </dependency>
    18. </dependencies>
    19. <dependencyManagement>
    20. <dependencies>
    21. <dependency>
    22. <groupId>org.springframework.cloud</groupId>
    23. <artifactId>spring-cloud-dependencies</artifactId>
    24. <version>Dalston.SR4</version>
    25. <type>pom</type>
    26. <scope>import</scope>
    27. </dependency>
    28. </dependencies>
    29. </dependencyManagement>

    注意:与 service-provider 相比,service-consumer 要演示 FeignClient 的使用,故 pom.xml 文件中增加了一个 spring-cloud-starter-feign 的依赖。

  2. 配置 RestTemplate、AsyncRestTemplate 和 FeignClient。

    1. FeignClient 是一个将HTTP 转为 RPC 格式调用的客户端。在使用他之前,我们需完成两项配置:

      1. @EnableFeignClient注解。

      2. 配置对应的 HTTP URL 地址及 HTTP 方法。

        1. @FeignClient(name = "service-provider")
        2. public interface EchoService{
        3. @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
        4. String echo(@PathVariable("str") String str);
        5. }
    2. 在启动类中:

      1. 使用 @EnableDiscoveryClient 注解启用服务注册与发现;

      2. 使用 @EnableFeignClients 注解激活 FeignClient;

      3. 添加 @LoadBalanced 注解将 RestTemplate 与 AsyncRestTemplate 与服务发现结合。

        1. @SpringBootApplication
        2. @EnableDiscoveryClient
        3. @EnableFeignClients
        4. public class ConsumerApplication {
        5. @LoadBalanced
        6. @Bean
        7. public RestTemplate restTemplate() {
        8. return new RestTemplate();
        9. }
        10. @LoadBalanced
        11. @Bean
        12. public AsyncRestTemplate asyncRestTemplate(){
        13. return new AsyncRestTemplate();
        14. }
        15. public static void main(String[] args) {
        16. SpringApplication.run(ConsumerApplication.class, args);
        17. }
        18. }
  3. 创建 Controller 以演示和验证服务发现功能。

    1. @RestController
    2. public class TestController {
    3. @Autowired
    4. private RestTemplate restTemplate;
    5. @Autowired
    6. private AsyncRestTemplate asyncRestTemplate;
    7. @Autowired
    8. private EchoService echoService;
    9. @RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
    10. public String rest(@PathVariable String str) {
    11. return restTemplate.getForObject("http://service-provider/echo/" + str, String.class);
    12. }
    13. @RequestMapping(value = "/echo-async-rest/{str}", method = RequestMethod.GET)
    14. public String asyncRest(@PathVariable String str) throws Exception{
    15. ListenableFuture<ResponseEntity<String>> future = asyncRestTemplate.
    16. getForEntity("http://service-provider/echo/"+str, String.class);
    17. return future.get().getBody();
    18. }
    19. @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
    20. public String feign(@PathVariable String str) {
    21. return echoService.echo(str);
    22. }
    23. }
  4. 添加应用基本配置和阿里云 AK、SK 以及 EDAS 的命名空间。

    1. spring.application.name=service-consumer
    2. server.port=18082
    3. alibaba.cloud.access-key=xxxxxxxxxx
    4. alibaba.cloud.secret-key=xxxxxxxxxx
    5. alibaba.edas.namespace=cn-hangzhou
  5. 登录 EDAS 控制台,进入服务管理 > 服务查询页面。选择地域命名空间,在服务查询页面查看服务注册的信息。可以在服务名列表查看到创建的服务实例 service-consumer。

  6. 分别调用我们的演示 API,可以看到调用成功的结果。

    服务调用

Demo 下载

更多配置项

配置项 key 默认值 说明 补充说明
服务名 spring.cloud.ans.doms spring.application.name 当此项未配置时,默认从spring.application.name中获取。需要发布多个服务时,中间用英文的“,”号隔开 production
是否注册 spring.cloud.ans.register-enabled true 当只需要发现,不需要注册时,可以通过将值设置成 false来关闭注册 production
想要注册的IP spring.cloud.ans.ip 当需要指定本机注册的IP时,通过此值来配置,优先级最高 production
想要注册的IP所属的网卡 spring.cloud.ans.interface-name 当确定需要发布哪块网卡对应的IP地址时,通过此参数配置,值为网卡名 production
想要注册的端口 spring.cloud.ans.port 自定义想要注册的端口 test
注册的权重 spring.cloud.ans.weight 1 数值越大权重越高 test
集群 spring.cloud.ans.cluster DEFAULT 可以通过集群来分别标记服务 test
租户环境 spring.cloud.ans.env 1 相同租户的相同环境下的服务才能互相发现 test

FAQ

  1. 我看到我的服务注册成功了,如何调用呢?

    答:spring-cloud-starter-ans 默认支持集成了 Ribbon,您可以使用 RestTemplate 和 FeignClient 调用。

  2. 为什么我的服务注册总是失败?

    答:如果您在确认账号信息都准确无误的情况下,但是运行此文档中的 Demo 却注册失败了。有可能是由于您本机的时间不准确,从而导致验签鉴权失败。此时您需要校正本机的时间,建议打开时间自动同步功能。

参考

更多详情请参考 ANS 使用指南