美文网首页
Spring Cloud Alibaba使用Nacos做注册中心

Spring Cloud Alibaba使用Nacos做注册中心

作者: Forward_233 | 来源:发表于2019-12-17 07:39 被阅读0次

    对在Spring Cloud Alibaba使用nacos做注册和动态配置中心,Feign远程调用,并实现负载均衡的学习过程做一下总结,希望大家共同进步。


    一. 安装nacos服务

    1. 具体安装步骤可参考这篇博客:
      https://blog.csdn.net/qq_32352777/article/details/86560333
      写的很不错,感谢作者。

    2. 安装问题总结

      • 测试环境一般建议安装单机版的,简单快速。集群安装的话,为了符合高可用的要求,MySQL也需要安装成集群形式。如Master-Slave模式。

      • 如果是在虚拟机上安装,一般的虚拟机我们不会给分配太大内存。所以我们得根据自己的机子内存情况修改一下nacos启动时默认分配的虚拟机内存,否则会启动失败,我们去查看nacos的安装目录下的log目录的nacos.log日志,会发现报内存不足的异常。

        (1)在nacos安装目录下,打开nacos启动脚本。

        vim  bin/startup.sh
        

        (2)vim模式下ctrl+f向后翻页,找到如下部分


        在这里插入图片描述

        (3)根据实际情况进行对nacos启动jvm虚拟机内存设置进行修改。

    二. 代码实现

    1. 创建父项目

      父pom,具体说明在注释里面

          <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <groupId>com.test</groupId>
          <artifactId>cloud-test</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <name>cloud-test</name>
          <packaging>pom</packaging>
      
          <!--子模块-->
          <modules>
              <module>cloud-service1</module>
              <module>cloud-service2</module>
              <module>cloud-consumer</module>
              <module>cloud-common</module>
          </modules>
      
          <!--依赖的组件的大版本号-->
          <properties>
              <java.version>1.8</java.version>
              <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
              <spring-cloud-alibaba.version>0.9.0.RELEASE</spring-cloud-alibaba.version>
              <spring-boot-starter-parent.version>2.2.2.RELEASE</spring-boot-starter-parent.version>
          </properties>
      
          <!--依赖jar包版本管理-->
          <dependencyManagement>
              <dependencies>
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-dependencies</artifactId>
                      <version>${spring-cloud.version}</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.cloud</groupId>
                      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                      <version>${spring-cloud-alibaba.version}</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
                  <dependency>
                      <groupId>org.springframework.boot</groupId>
                      <artifactId>spring-boot-starter-parent</artifactId>
                      <version>${spring-boot-starter-parent.version}</version>
                      <type>pom</type>
                      <scope>import</scope>
                  </dependency>
              </dependencies>
          </dependencyManagement>
              
          <dependencies>
              <!--服务发现(注册中心)-->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
              </dependency>
              <!--配置中心-->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <dependency>
                  <groupId>com.alibaba</groupId>
                  <artifactId>fastjson</artifactId>
                  <version>LATEST</version>
              </dependency>
              <dependency>
                  <groupId>org.projectlombok</groupId>
                  <artifactId>lombok</artifactId>
                  <optional>true</optional>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
          </dependencies>
      </project>
      

      项目结构图:

      在这里插入图片描述
    2. 创建公共子模块

      公共做模块是放服务调用的接口和一些公共实体类和公共工具的。结构如下:

      在这里插入图片描述

      pom文件:

          <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <artifactId>cloud-consumer</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <name>cloud-consumer</name>
          <packaging>jar</packaging>
      
          <parent>
              <groupId>com.test</groupId>
              <artifactId>cloud-test</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </parent>
      
          <properties>
              <java.version>1.8</java.version>
          </properties>
      
          <dependencies>
      
              <dependency>
                  <groupId>com.test</groupId>
                  <artifactId>cloud-common</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-openfeign</artifactId>
              </dependency>
          </dependencies>
      </project>
      

      创建一个测试的实体类User

      package com.common.model;
      
      import lombok.Data;
      
      /**
       * Author: yhl
       * DateTime: 2019/12/8 23:13
       * Description: write some description
       */
      @Data
      public class User {
          private Long id;
          private String name;
          private String url;
      }
      

      创建微服务调用的接口IUserService

      package com.common.service;
      
      import com.common.model.User;
      import org.springframework.web.bind.annotation.RequestBody;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      
      import java.util.Map;
      
      /**
       * Author: yhl
       * DateTime: 2019/12/8 23:13
       * Description: write some description
       */
      public interface IUserService {
      
          @RequestMapping("/testOut")
          Map<Object,Object> test(@RequestParam("name") String name);
      
          @RequestMapping("/testOutObj")
          User testObj(@RequestBody User user);
      
          @RequestMapping("/testNacosDynamicProp")
          String testNacosDynamicProp();
      }
      

      配置文件application.yml可以放置一些公共的参数配置,比如加解密私钥等等

    3. 创建服务提供者

      此模块为服务提供方,实现真正的业务逻辑。结构如下:

      在这里插入图片描述

      为了测试Feign的负载均衡,创建两个一样结构和内容的服务提供者,分别命名为cloud-service1和cloud-service2,在它们各自的application.yml中,使用不同的端口号来模拟不同地址的相同的服务。

      pom:

          <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <parent>
              <groupId>com.test</groupId>
              <artifactId>cloud-test</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </parent>
          <artifactId>cloud-service1</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <name>cloud-service1</name>
          <packaging>jar</packaging>
      
          <properties>
              <java.version>1.8</java.version>
          </properties>
      
          <dependencies>
      
              <!--引入公共模块-->
              <dependency>
                  <groupId>com.test</groupId>
                  <artifactId>cloud-common</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
              </dependency>
          </dependencies>
      </project>
      

      创建配置文件bootstrap.yaml和application.yml

      bootstrap.yml如下:

      spring:
      application:
      # 服务提供者名称
      name: cloud-service
      cloud:
      nacos:
        discovery:
          # 服务注册于发现地址
          server-addr: 192.168.31.217:8848
        config:
          # 配置中心地址
          server-addr: ${spring.cloud.nacos.discovery.server-addr}
          # 配置中心配置文件的格式,如果不设置此项,默认为.properties格式
          file-extension: yaml
      

      application.yml如下:

      #服务端口,这里我们设置cloud-service1为8001,cloud-service2为8002
      server:
        port: 8081
      

      有了application.yml,为什么还要创建一个bootstrap.yml呢,它们俩的区别如下:

      https://blog.csdn.net/ThinkWon/article/details/100007093

      感谢这篇文章的作者,解开了我的迷惑。

      创建启动类ServiceApplication1

      package com.service;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
      
      @SpringBootApplication
      public class ServiceApplication1 {
      
          public static void main(String[] args) {
              SpringApplication.run(ServiceApplication1.class, args);
          }
      
      }
      

      创建服务提供类UserServiceProvider

      package com.service.controller;
      
      import com.common.model.User;
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.cloud.context.config.annotation.RefreshScope;
      import org.springframework.web.bind.annotation.RequestBody;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RequestParam;
      import org.springframework.web.bind.annotation.RestController;
      
      import javax.servlet.http.HttpServletRequest;
      import java.util.HashMap;
      import java.util.Map;
      
      /**
       * Author: yhl
       * DateTime: 2019/12/8 23:17
       * Description: write some description
       */
      @RestController
      public class UserServiceProvider {
      
          @RequestMapping("/testOut")
          public Map test(@RequestParam("name") String name, HttpServletRequest req) {
              Map<Object, Object> map = new HashMap<>();
              map.put("url", req.getRequestURL().toString());
              map.put("name", name);
              return map;
          }
      
          @RequestMapping("/testOutObj")
          public User testObj(@RequestBody() User user, HttpServletRequest req) {
              user.setUrl(req.getRequestURL().toString());
              return user;
          }
      }
      

      服务提供者创建完成。

    1. 创建服务消费者cloud-consumer

      pom文件:

          <?xml version="1.0" encoding="UTF-8"?>
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <artifactId>cloud-consumer</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <name>cloud-consumer</name>
          <packaging>jar</packaging>
      
          <parent>
              <groupId>com.test</groupId>
              <artifactId>cloud-test</artifactId>
              <version>0.0.1-SNAPSHOT</version>
          </parent>
      
          <properties>
              <java.version>1.8</java.version>
          </properties>
      
          <dependencies>
              <dependency>
                  <groupId>com.test</groupId>
                  <artifactId>cloud-common</artifactId>
                  <version>0.0.1-SNAPSHOT</version>
              </dependency>
              
              <!-Feign--->
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-openfeign</artifactId>
              </dependency>
          </dependencies>
      </project>
      

      因为远程调用使用的是Feign组件,所以pom中加了Feign的依赖。

      创建配置文件bootstrap.yaml和application.yml

      bootstrap.yml如下:

      spring:
      application:
      # 服务提供者名称
      name: cloud-consumer
      cloud:
      nacos:
        discovery:
          # 服务注册于发现地址
          server-addr: 192.168.31.217:8848
        config:
          # 配置中心地址
          server-addr: ${spring.cloud.nacos.discovery.server-addr}
          # 配置中心配置文件的格式,如果不设置此项,默认为.properties格式
          file-extension: yaml
      

      application.yml如下:

      #服务端口,这里我们设置cloud-service1为8001,cloud-service2为8002
      server:
        port: 8080
      

      创建服务消费者启动类ConsumerApplication

      package com.consumer;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.boot.autoconfigure.SpringBootApplication;
      import org.springframework.cloud.openfeign.EnableFeignClients;
      
      @SpringBootApplication
      @EnableFeignClients//开启feign
      public class ConsumerApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(ConsumerApplication.class, args);
          }
      }
      

      在启动类上加@EnableFeignClients,代表开启了对feign组件的支持。

      继承服务提供方接口UserService

      @FeignClient(name ="cloud-service")
      public interface UserService extends IUserService {
      }
      

      此接口方法继承了我们在common模块定义的微服务接口,加上@FeignClient注解之后,表示可使用Feign来调用此接口中方法中@RequestMapping映射路径的服务提供者的http服务。
      此接口是我抽象出来的,目的是不用在common模块中也引入Feign的依赖,当然也可以不用这么写。直接在IUserService接口加上@FeignClient注解。

      @FeignClient中的name属性配置的为bootstrap.yml中配置的服务提供者名称。

      创建消费者接口UserConsumerController

      package com.consumer.controller;
      
      import com.common.model.User;
      import com.consumer.service.UserService;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      import java.util.Map;
      
      /**
       * Author: yhl
       * DateTime: 2019/12/8 23:12
       * Description: write some description
       */
      @RestController
      public class UserConsumerController {
      
          @Autowired
          private UserService userService;
      
          @RequestMapping("/test")
          public Map<Object,Object> test() {
              return userService.test("张三");
          }
      
          @RequestMapping("/testObj")
          public User testObj() {
              return userService.testObj(new User());
          }
      
          @RequestMapping("/testNacosDynamicProp")
          public String testNacosDynamicProp() {
              return userService.testNacosDynamicProp();
          }
      }
      

      创建负载均衡配置类ConfigBean

      package com.consumer.config;
      
      import org.springframework.cloud.client.loadbalancer.LoadBalanced;
      import org.springframework.context.annotation.Bean;
      import org.springframework.context.annotation.Configuration;
      import org.springframework.web.client.RestTemplate;
      
      /**
       * @author: yhl
       * @DateTime: 2019/12/9 13:37
       * @Description:
       */
      
      @Configuration
      public class ConfigBean {
          /**
           * 默认按顺序轮询
           * @return
           */
          @Bean
          @LoadBalanced
          public RestTemplate getRestTemplate() {
              return new RestTemplate();
          }
      }
      

      至此,我们的模块都创建完毕了,接下来进行测试。

    2. 服务和负载均衡测试

      我们将三个模块的服务都启动,如下图:


      在这里插入图片描述

      利用http接口测试工具来测试我们的接口

      选择一个接口进行测试,如 http://localhost:8080/test

      在这里插入图片描述
      在这里插入图片描述

      发送两次请求,会发现打印的请求地址的端口号不同,说明实现了负载均衡。
      连续发送多次请求,端口号会交替变化,因为默认的负载均衡策略为轮训法。

       由于本片内容过程长,关于feign的负载均衡,单独再开一篇blog,感兴趣的话可以接着看
      

      Blog传送门

      本项目代码传送门

      有什么问题欢迎大家交流。

    相关文章

      网友评论

          本文标题:Spring Cloud Alibaba使用Nacos做注册中心

          本文链接:https://www.haomeiwen.com/subject/gdgjnctx.html