Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用

对在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向后翻页,找到如下部分


      Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用_第1张图片
      在这里插入图片描述

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

二. 代码实现

  1. 创建父项目

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

        
    
        4.0.0
        com.test
        cloud-test
        0.0.1-SNAPSHOT
        cloud-test
        pom
    
        
        
            cloud-service1
            cloud-service2
            cloud-consumer
            cloud-common
        
    
        
        
            1.8
            Hoxton.RELEASE
            0.9.0.RELEASE
            2.2.2.RELEASE
        
    
        
        
            
                
                    org.springframework.cloud
                    spring-cloud-dependencies
                    ${spring-cloud.version}
                    pom
                    import
                
                
                    org.springframework.cloud
                    spring-cloud-alibaba-dependencies
                    ${spring-cloud-alibaba.version}
                    pom
                    import
                
                
                    org.springframework.boot
                    spring-boot-starter-parent
                    ${spring-boot-starter-parent.version}
                    pom
                    import
                
            
        
            
        
            
            
                org.springframework.cloud
                spring-cloud-starter-alibaba-nacos-discovery
            
            
            
                org.springframework.cloud
                spring-cloud-starter-alibaba-nacos-config
            
            
                org.springframework.boot
                spring-boot-starter-web
            
            
                com.alibaba
                fastjson
                LATEST
            
            
                org.projectlombok
                lombok
                true
            
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
        
    
    

    项目结构图:

    Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用_第2张图片
    在这里插入图片描述
  2. 创建公共子模块

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

    Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用_第3张图片
    在这里插入图片描述

    pom文件:

        
    
        4.0.0
        cloud-consumer
        0.0.1-SNAPSHOT
        cloud-consumer
        jar
    
        
            com.test
            cloud-test
            0.0.1-SNAPSHOT
        
    
        
            1.8
        
    
        
    
            
                com.test
                cloud-common
                0.0.1-SNAPSHOT
            
    
            
                org.springframework.cloud
                spring-cloud-starter-openfeign
            
        
    
    

    创建一个测试的实体类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 test(@RequestParam("name") String name);
    
        @RequestMapping("/testOutObj")
        User testObj(@RequestBody User user);
    
        @RequestMapping("/testNacosDynamicProp")
        String testNacosDynamicProp();
    }
    

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

  3. 创建服务提供者

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

    Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用_第4张图片
    在这里插入图片描述

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

    pom:

        
    
        4.0.0
        
            com.test
            cloud-test
            0.0.1-SNAPSHOT
        
        cloud-service1
        0.0.1-SNAPSHOT
        cloud-service1
        jar
    
        
            1.8
        
    
        
    
            
            
                com.test
                cloud-common
                0.0.1-SNAPSHOT
            
        
    
    

    创建配置文件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 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文件:

        
    
        4.0.0
        cloud-consumer
        0.0.1-SNAPSHOT
        cloud-consumer
        jar
    
        
            com.test
            cloud-test
            0.0.1-SNAPSHOT
        
    
        
            1.8
        
    
        
            
                com.test
                cloud-common
                0.0.1-SNAPSHOT
            
            
            
            
                org.springframework.cloud
                spring-cloud-starter-openfeign
            
        
    
    

    因为远程调用使用的是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 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. 服务和负载均衡测试

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


    Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用_第5张图片
    在这里插入图片描述

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

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

    Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用_第6张图片
    在这里插入图片描述

    Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用_第7张图片
    在这里插入图片描述

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

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

    Blog传送门

    本项目代码传送门

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

你可能感兴趣的:(Spring Cloud Alibaba使用Nacos做注册中心,Feign负载均衡远程调用)