• SpringCloud:Nacos注册中心和服务消费方式


    目录

    一、nacos环境搭建

    nacos简介

    步骤1:安装nacos

    步骤2:启动nacos

    启动

     步骤3:访问nacos

    二、nacos的微服务注册

    ①导入pom依赖

    shop-common的pom.xml

    父工程的pom

    ②加注解

     ③在application.yml中添加nacos服务的地址

      ④启动服务

    三、负载均衡实现

    第一种:DiscoveryClient

     OrderCtroller_DiscoveryClient

    第二种:Ribbon

     ShopOrderApplication 

     OrderCtroller_Ribbon 

    第三种:Feign

    Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务 一样简单, 只需要创建一个接口并添加一个注解即可。 Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负 载均衡的效果。

    ①加入Fegin的依赖

    shop-common的pom

    ②在主类上添加Fegin的注解

     ShopOrderApplication 

    ③创建一个service, 并使用Fegin实现微服务调用

    ProductService 

     OrderCtroller_Fegin 

    四、Feign传参

    FeignServerController 

     ProductService 

     FeignClintController 


    一、nacos环境搭建

    我们已经可以实现微服务之间的调用。但是我们把服务提供者的网络地址 (ip,端口)等硬编码到了代码中,这种做法存在许多问题:

    • 一旦服务提供者地址变化,就需要手工修改代码

    • 一旦是多个服务提供者,无法实现负载均衡功能

    • 一旦服务变得越来越多,人工维护调用关系困难

    那么应该怎么解决呢, 这时候就需要通过注册中心动态的实现服务治理。
    什么是服务治理  服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的 自动化注册

    nacos简介

    Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速 实现动态服务发现、服务配置、服务元数据及流量管理。 从上面的介绍就可以看出,nacos的作用就是一个注册中心,用来管理注册上来的各个微服务。

    步骤1:安装nacos

    下载地址: https://github.com/alibaba/nacos/releases
    下载zip格式的安装包,然后进行解压缩操作

    下载以及解压后

    步骤2:启动nacos

    #切换目录
    cd nacos/bin
    #命令启动
    startup.cmd -m standalone

    或者直接修改startup.cmd文件:set MODE="standalone

    修改前

     修改后

    启动

     

     步骤3:访问nacos

    打开浏览器输入http://localhost:8848/nacos,即可访问服务, 账户和默认密码是nacos/nacos

    二、nacos的微服务注册

    将商品微服务注册到nacos

    ①导入pom依赖

    接下来开始修改shop-product 模块的代码, 将其注册到nacos服务上 1 在shop-common模块的pom.xml中添加nacos的依赖

    
    
        com.alibaba.cloud
        spring-cloud-starter-alibaba-nacos-discovery
    

    注意在父模块中是否导入了alibaba

    1. <dependencyManagement>
    2. <dependencies>
    3. <dependency>
    4. <groupId>org.springframework.cloudgroupId>
    5. <artifactId>spring-cloud-dependenciesartifactId>
    6. <version>${spring-cloud.version}version>
    7. <type>pomtype>
    8. <scope>importscope>
    9. dependency>
    10. <dependency>
    11. <groupId>com.alibaba.cloudgroupId>
    12. <artifactId>spring-cloud-alibaba-dependenciesartifactId>
    13. <version>${spring-cloud-alibaba.version}version>
    14. <type>pomtype>
    15. <scope>importscope>
    16. dependency>
    17. dependencies>
    18. dependencyManagement>

    shop-common的pom.xml

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <parent>
    6. <artifactId>spcloud-shopartifactId>
    7. <groupId>com.cdlgroupId>
    8. <version>1.0-SNAPSHOTversion>
    9. parent>
    10. <modelVersion>4.0.0modelVersion>
    11. <artifactId>shop-commonartifactId>
    12. <dependencies>
    13. <dependency>
    14. <groupId>org.projectlombokgroupId>
    15. <artifactId>lombokartifactId>
    16. dependency>
    17. <dependency>
    18. <groupId>com.alibabagroupId>
    19. <artifactId>fastjsonartifactId>
    20. <version>1.2.56version>
    21. dependency>
    22. <dependency>
    23. <groupId>mysqlgroupId>
    24. <artifactId>mysql-connector-javaartifactId>
    25. <version>5.1.44version>
    26. dependency>
    27. <dependency>
    28. <groupId>com.alibaba.cloudgroupId>
    29. <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    30. dependency>
    31. dependencies>
    32. project>

    父工程的pom

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <modelVersion>4.0.0modelVersion>
    6. <groupId>com.cdlgroupId>
    7. <artifactId>spcloud-shopartifactId>
    8. <version>1.0-SNAPSHOTversion>
    9. <modules>
    10. <module>shop-commonmodule>
    11. <module>shop-ordermodule>
    12. <module>shop-productmodule>
    13. <module>shop-usermodule>
    14. modules>
    15. <packaging>pompackaging>
    16. <properties>
    17. <java.version>1.8java.version>
    18. <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
    19. <project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
    20. <spring-boot.version>2.3.2.RELEASEspring-boot.version>
    21. <spring-cloud.version>Hoxton.SR9spring-cloud.version>
    22. <spring-cloud-alibaba.version>2.2.6.RELEASEspring-cloud-alibaba.version>
    23. properties>
    24. <dependencyManagement>
    25. <dependencies>
    26. <dependency>
    27. <groupId>org.springframework.bootgroupId>
    28. <artifactId>spring-boot-dependenciesartifactId>
    29. <version>${spring-boot.version}version>
    30. <type>pomtype>
    31. <scope>importscope>
    32. dependency>
    33. <dependency>
    34. <groupId>org.springframework.cloudgroupId>
    35. <artifactId>spring-cloud-dependenciesartifactId>
    36. <version>${spring-cloud.version}version>
    37. <type>pomtype>
    38. <scope>importscope>
    39. dependency>
    40. <dependency>
    41. <groupId>com.alibaba.cloudgroupId>
    42. <artifactId>spring-cloud-alibaba-dependenciesartifactId>
    43. <version>${spring-cloud-alibaba.version}version>
    44. <type>pomtype>
    45. <scope>importscope>
    46. dependency>
    47. dependencies>
    48. dependencyManagement>
    49. project>

    ②加注解

    在主类上添加@EnableDiscoveryClient(用于开启远程连接)注解

     ③在application.yml中添加nacos服务的地址

    spring:
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848

      ④启动服务

    观察nacos的控制面板中是否有注册上来的商品微服务

    运行订单

     

     再运行一个商品

    三、负载均衡实现

    第一种:DiscoveryClient

    创建集群

     

     

     运行8081

     

     

     

     将启动类都运行

     

     对应的端口号:

     刷新页面

    对应的端口号:

     OrderCtroller_DiscoveryClient

    1. package com.cdl.shoporder.Controller;
    2. import com.cdl.model.Order;
    3. import com.cdl.model.Product;
    4. import com.cdl.model.User;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.cloud.client.ServiceInstance;
    7. import org.springframework.cloud.client.discovery.DiscoveryClient;
    8. import org.springframework.http.HttpRequest;
    9. import org.springframework.web.bind.annotation.PathVariable;
    10. import org.springframework.web.bind.annotation.RequestMapping;
    11. import org.springframework.web.bind.annotation.RestController;
    12. import org.springframework.web.client.RestTemplate;
    13. import java.util.List;
    14. import java.util.Random;
    15. /**
    16. * @author cdl
    17. * @site www.cdl.com
    18. * @create 2022-11-25 15:43
    19. */
    20. @RestController
    21. @RequestMapping("/order")
    22. public class OrderCtroller_DiscoveryClient {
    23. @Autowired
    24. private RestTemplate restTemplate;
    25. @Autowired
    26. private DiscoveryClient discoveryClient;
    27. @RequestMapping("/get/{uid}/{pid}")
    28. public Order get(@PathVariable("uid") Integer uid,
    29. @PathVariable("pid") Integer pid
    30. ){
    31. //我们可以通过服务名拿到多个节点的信息
    32. List instances = discoveryClient.getInstances("shop-product");
    33. // 随机产生0或者1的整数
    34. int index = new Random().nextInt(instances.size());
    35. ServiceInstance serviceInstance = instances.get(index);
    36. String url = serviceInstance.getHost() + ":" +
    37. serviceInstance.getPort();
    38. //通过restTemplate调用商品微服务
    39. User user = restTemplate.getForObject("http://localhost:8070/user/get/" + uid, User.class);
    40. Product product = restTemplate.getForObject("http://" + url +
    41. "/product/get/" + pid, Product.class);
    42. Order order = new Order();
    43. order.setUsername(user.getUsername());
    44. order.setUid(user.getUid());
    45. order.setPprice(product.getPprice());
    46. order.setPname(product.getPname());
    47. order.setPid(product.getPid());
    48. order.setOid(System.currentTimeMillis());
    49. order.setNumber(product.getStock());
    50. return order;
    51. }
    52. }

    第二种:Ribbon

    Ribbon是Spring Cloud的一个组件, 它可以让我们使用一个注解就能轻松的搞定负载均衡

    在RestTemplate 的生成方法上添加@LoadBalanced注解

     ShopOrderApplication 

    1. package com.cdl.shoporder;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    6. import org.springframework.context.annotation.Bean;
    7. import org.springframework.web.client.RestTemplate;
    8. @EnableDiscoveryClient
    9. @SpringBootApplication
    10. public class ShopOrderApplication {
    11. public static void main(String[] args) {
    12. SpringApplication.run(ShopOrderApplication.class, args);
    13. }
    14. @LoadBalanced //ribbon负载均衡添加
    15. @Bean
    16. public RestTemplate restTemplate(){
    17. return new RestTemplate();
    18. }
    19. }

     OrderCtroller_Ribbon 

    1. package com.cdl.shoporder.Controller;
    2. import com.cdl.model.Order;
    3. import com.cdl.model.Product;
    4. import com.cdl.model.User;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.web.bind.annotation.PathVariable;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.RestController;
    9. import org.springframework.web.client.RestTemplate;
    10. /**
    11. * @author cdl
    12. * @site www.cdl.com
    13. * @create 2022-11-25 15:43
    14. */
    15. @RestController
    16. @RequestMapping("/order")
    17. public class OrderCtroller_Ribbon {
    18. @Autowired
    19. private RestTemplate restTemplate;
    20. @RequestMapping("/get/{uid}/{pid}")
    21. public Order get(@PathVariable("uid") Integer uid,
    22. @PathVariable("pid") Integer pid){
    23. //要在订单微服务中调用 用户微服务、商品微服务 跨项目调用
    24. // 当采用http:/shop-user/user/get/访问第三方服务,那么http://localhost:8070/user/get/就用不了了
    25. User user = restTemplate.getForObject("http://shop-user/user/get/" + uid, User.class);
    26. Product product = restTemplate.getForObject("http://shop-product/product/get/" + pid, Product.class);
    27. Order order = new Order();
    28. order.setUsername(user.getUsername());
    29. order.setUid(user.getUid());
    30. order.setPprice(product.getPprice());
    31. order.setPname(product.getPname());
    32. order.setPid(product.getPid());
    33. order.setOid(System.currentTimeMillis());
    34. order.setNumber(product.getStock());
    35. return order;
    36. }
    37. }

    启动项目

    页面访问 也能访问到 

    第三种:Feign

    什么是Feign

    Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务 一样简单, 只需要创建一个接口并添加一个注解即可。 Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负 载均衡的效果。

    ①加入Fegin的依赖



        org.springframework.cloud
        spring-cloud-starter-openfeign

    shop-common的pom

    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"
    3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    5. <parent>
    6. <artifactId>spcloud-shopartifactId>
    7. <groupId>com.cdlgroupId>
    8. <version>1.0-SNAPSHOTversion>
    9. parent>
    10. <modelVersion>4.0.0modelVersion>
    11. <artifactId>shop-commonartifactId>
    12. <dependencies>
    13. <dependency>
    14. <groupId>org.projectlombokgroupId>
    15. <artifactId>lombokartifactId>
    16. dependency>
    17. <dependency>
    18. <groupId>com.alibabagroupId>
    19. <artifactId>fastjsonartifactId>
    20. <version>1.2.56version>
    21. dependency>
    22. <dependency>
    23. <groupId>mysqlgroupId>
    24. <artifactId>mysql-connector-javaartifactId>
    25. <version>5.1.44version>
    26. dependency>
    27. <dependency>
    28. <groupId>com.alibaba.cloudgroupId>
    29. <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    30. dependency>
    31. <dependency>
    32. <groupId>org.springframework.cloudgroupId>
    33. <artifactId>spring-cloud-starter-openfeignartifactId>
    34. dependency>
    35. dependencies>
    36. project>

    ②在主类上添加Fegin的注解

    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients//开启Fegin
    public class OrderApplication {}

     ShopOrderApplication 

    1. package com.cdl.shoporder;
    2. import org.springframework.boot.SpringApplication;
    3. import org.springframework.boot.autoconfigure.SpringBootApplication;
    4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    6. import org.springframework.cloud.openfeign.EnableFeignClients;
    7. import org.springframework.context.annotation.Bean;
    8. import org.springframework.web.client.RestTemplate;
    9. @EnableFeignClients//开启Fegin
    10. @EnableDiscoveryClient
    11. @SpringBootApplication
    12. public class ShopOrderApplication {
    13. public static void main(String[] args) {
    14. SpringApplication.run(ShopOrderApplication.class, args);
    15. }
    16. @LoadBalanced //ribbon负载均衡添加
    17. @Bean
    18. public RestTemplate restTemplate(){
    19. return new RestTemplate();
    20. }
    21. }

    ③创建一个service, 并使用Fegin实现微服务调用

    ProductService 

    1. package com.cdl.shoporder.service;
    2. import com.cdl.model.Product;
    3. import org.springframework.cloud.openfeign.FeignClient;
    4. import org.springframework.web.bind.annotation.GetMapping;
    5. import org.springframework.web.bind.annotation.PathVariable;
    6. import org.springframework.web.bind.annotation.RequestMapping;
    7. import javax.servlet.http.HttpServletRequest;
    8. /**
    9. * @author cdl
    10. * @site www.cdl.com
    11. * @create 2022-11-28 12:14
    12. *
    13. * 帮助消费者 shop-order 调用生产者 shop-product
    14. */
    15. @FeignClient("shop-product")//声明调用的提供者的name
    16. public interface ProductService {
    17. //接口定义:完全遵守restful接口规范 controller怎么写 这里就怎么写
    18. // 注意:记得加上载化路径
    19. @RequestMapping("/product/get/{pid}")
    20. public Product get(@PathVariable("pid") Integer pid);
    21. }

     OrderCtroller_Fegin 

    1. package com.cdl.shoporder.Controller;
    2. import com.cdl.model.Order;
    3. import com.cdl.model.Product;
    4. import com.cdl.model.User;
    5. import com.cdl.shoporder.service.ProductService;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.web.bind.annotation.PathVariable;
    8. import org.springframework.web.bind.annotation.RequestMapping;
    9. import org.springframework.web.bind.annotation.RestController;
    10. import org.springframework.web.client.RestTemplate;
    11. /**
    12. * @author cdl
    13. * @site www.cdl.com
    14. * @create 2022-11-25 15:43
    15. */
    16. @RestController
    17. @RequestMapping("/order")
    18. public class OrderCtroller_Fegin {
    19. @Autowired
    20. private ProductService productService;
    21. @Autowired
    22. private RestTemplate restTemplate;
    23. @RequestMapping("/get/{uid}/{pid}")
    24. public Order get(@PathVariable("uid") Integer uid,
    25. @PathVariable("pid") Integer pid){
    26. User user = restTemplate.getForObject("http://shop-user/user/get/" + uid, User.class);
    27. Product product = productService.get(pid);
    28. Order order = new Order();
    29. order.setUsername(user.getUsername());
    30. order.setUid(user.getUid());
    31. order.setPprice(product.getPprice());
    32. order.setPname(product.getPname());
    33. order.setPid(product.getPid());
    34. order.setOid(System.currentTimeMillis());
    35. order.setNumber(product.getStock());
    36. return order;
    37. }
    38. }

    启动项目

    四、Feign传参

    FeignServerController 

    1. package com.cdl.shopproduct.Controller;
    2. import com.cdl.model.Product;
    3. import lombok.extern.slf4j.Slf4j;
    4. import org.springframework.web.bind.annotation.PathVariable;
    5. import org.springframework.web.bind.annotation.RequestBody;
    6. import org.springframework.web.bind.annotation.RequestMapping;
    7. import org.springframework.web.bind.annotation.RequestParam;
    8. import org.springframework.web.bind.annotation.RestController;
    9. @Slf4j
    10. @RestController
    11. @RequestMapping("/feignServer")
    12. public class FeignServerController {
    13. @RequestMapping("/findByParameter")
    14. public String findByParameter(String name,Double price){
    15. log.info("服务提供者日志:{}",name);
    16. return "hello:"+name;
    17. }
    18. @RequestMapping("/findByParameter2")
    19. public String findByParameter2(
    20. @RequestParam("name") String name,
    21. @RequestParam("price") Double price){
    22. log.info("服务提供者日志:{},{}",name,price);
    23. return "hello:"+name+price;
    24. }
    25. @RequestMapping("/findByPathVariable/{name}")
    26. public String findByPathVariable(@PathVariable("name") String name){
    27. log.info("服务提供者日志:{}",name);
    28. return "hello:"+name;
    29. }
    30. @RequestMapping("/findByRequestBody")
    31. public Product findByRequestBody(@RequestBody Product product){
    32. log.info("服务提供者日志:{}",product.getPname());
    33. return product;
    34. }
    35. }

     ProductService 

    1. package com.cdl.shoporder.service;
    2. import com.cdl.model.Product;
    3. import org.springframework.cloud.openfeign.FeignClient;
    4. import org.springframework.web.bind.annotation.GetMapping;
    5. import org.springframework.web.bind.annotation.PathVariable;
    6. import org.springframework.web.bind.annotation.RequestBody;
    7. import org.springframework.web.bind.annotation.RequestMapping;
    8. import org.springframework.web.bind.annotation.RequestParam;
    9. import javax.servlet.http.HttpServletRequest;
    10. /**
    11. * @author cdl
    12. * @site www.cdl.com
    13. * @create 2022-11-28 12:14
    14. *
    15. * 帮助消费者 shop-order 调用生产者 shop-product
    16. */
    17. @FeignClient("shop-product")//声明调用的提供者的name
    18. public interface ProductService {
    19. //接口定义:完全遵守restful接口规范 controller怎么写 这里就怎么写
    20. // 注意:记得加上载化路径
    21. @RequestMapping("/product/get/{pid}")
    22. public Product get(@PathVariable("pid") Integer pid);
    23. @RequestMapping("/feignServer/findByParameter")
    24. public String findByParameter( @RequestParam("name") String name,@RequestParam("price") Double price);
    25. @RequestMapping("/feignServer/findByParameter2")
    26. public String findByParameter2(
    27. @RequestParam("name") String name,
    28. @RequestParam("price") Double price);
    29. @RequestMapping("/feignServer/findByPathVariable/{name}")
    30. public String findByPathVariable(@PathVariable("name") String name);
    31. @RequestMapping("/feignServer/findByRequestBody")
    32. public Product findByRequestBody(@RequestBody Product product);
    33. }

     FeignClintController 

    1. package com.cdl.shoporder.Controller;
    2. import com.cdl.model.Product;
    3. import com.cdl.shoporder.service.ProductService;
    4. import lombok.extern.slf4j.Slf4j;
    5. import org.checkerframework.checker.units.qual.A;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.web.bind.annotation.PathVariable;
    8. import org.springframework.web.bind.annotation.RequestBody;
    9. import org.springframework.web.bind.annotation.RequestMapping;
    10. import org.springframework.web.bind.annotation.RequestParam;
    11. import org.springframework.web.bind.annotation.RestController;
    12. @Slf4j
    13. @RestController
    14. @RequestMapping("/feignClint")
    15. public class FeignClintController {
    16. @Autowired
    17. private ProductService productService;
    18. @RequestMapping("/findByParameter")
    19. public String findByParameter(@RequestParam("name")String name,@RequestParam("price") Double price){
    20. log.info("服务消费者日志:{}",name);
    21. return productService.findByParameter(name,price);
    22. }
    23. @RequestMapping("/findByParameter2")
    24. public String findByParameter2(
    25. @RequestParam("name") String name,
    26. @RequestParam("price") Double price){
    27. log.info("服务消费者日志:{},{}",name,price);
    28. return productService.findByParameter2(name,price);
    29. }
    30. @RequestMapping("/findByPathVariable/{name}")
    31. public String findByPathVariable(@PathVariable("name") String name){
    32. log.info("服务消费者日志:{}",name);
    33. return productService.findByPathVariable(name);
    34. }
    35. @RequestMapping("/findByRequestBody")
    36. public Product findByRequestBody(@RequestBody Product product){
    37. log.info("服务消费者日志:{}",product.getPname());
    38. return product;
    39. }
    40. }

     

     

  • 相关阅读:
    linux 容量调整
    如何批量上传Maven仓库jar包到Nexus3.x私服
    微信小程序连接后端案例
    基于混合模型磁链观测器的异步电机矢量控制的学习
    5G投资下降,遥遥领先的主流5G或被运营商抛弃,“假5G”更获青睐
    Unity基于Text的快捷键修改组件
    解决Python无法写入Mongodb数据仓库方法汇总
    微信小程序新版隐私协议弹窗实现最新版
    C语言入门Day_18 判断和循坏的小结
    java通过socket实现https get 请求网页
  • 原文地址:https://blog.csdn.net/weixin_62735525/article/details/128073882