• SpringCloud服务治理介绍&Nacos安装及实现负载均衡


    目录

    一、服务治理简介

    二、nacos简介

    三、nacos下载&安装

    四、nacos实现负载均衡


    一、服务治理简介

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

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

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

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

    那么应该怎么解决呢, 这时候就需要通过注册中心动态实现服务治理。

    1.1什么是服务治理?

    服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动化注册与发现

    1.2注册中心的作用?

    通过上面的调用图会发现,除了微服务,还有一个组件是服务注册中心,它是微服务架构非常重要 的一个组件,在微服务架构里主要起到了协调者的一个作用。注册中心一般包含如下几个功能:

    服务发现:

    • 服务注册:保存服务提供者和服务调用者的信息

    • 服务订阅(发现):服务调用者订阅服务提供者的信息,注册中心向订阅者推送提供者的信息

    服务配置:

    • 配置订阅:服务提供者和服务调用者订阅微服务相关的配置

    • 配置下发:主动将配置推送给服务提供者和服务调用者

    服务健康检测

    • 检测服务提供者的健康情况,如果发现异常,执行服务剔除

    1.3常见的注册中心有哪些?

    • Zookeeper zookeeper是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式 应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用 配置项的管理等。

    • Eureka Eureka是Springcloud Netflix中的重要组件,主要作用就是做服务注册和发现。但是现在已经闭 源

    • Consul Consul是基于GO语言开发的开源工具,主要面向分布式,服务化的系统提供服务注册、服务发现 和配置管理的功能。Consul的功能都很实用,其中包括:服务注册/发现、健康检查、Key/Value 存储、多数据中心和分布式一致性保证等特性。Consul本身只是一个二进制的可执行文件,所以 安装和部署都非常简单,只需要从官网下载后,在执行对应的启动脚本即可。

    • Nacos Nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。它是 Spring Cloud Alibaba 组件之一,负责服务注册发现和服务配置,可以这样认为nacos=eureka+config。

    二、nacos简介

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

    三、nacos下载&安装

    3.1下载地址

    https://github.com/alibaba/nacos/releases

    3.2安装步骤

    ①下载好压缩包进行解压

    ②修改bin目录下的startup.cmd文件

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

    ④启动Nacos

    修改startup.cmd后直接双击运行打开

    ⑤直接访问nacos

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

     到这里我们的nacos的下载及安装就完成了!

    四、nacos实现负载均衡

    我们接下来实现使用Nacos注册中心来解决负载均衡的问题,俺么首先第一步就是需要将我们所创建的微服务注册到Nacos中去

    4.1将微服务注册到Nacos

    这里就以商品微服务为例子:

    在父模块中是否导入了alibaba的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.zqgroupId>
    7. <artifactId>springcloud-shopartifactId>
    8. <version>1.0-SNAPSHOTversion>
    9. <modules>
    10. <module>shop-commonmodule>
    11. <module>shop-usermodule>
    12. <module>shop-productmodule>
    13. <module>shop-ordermodule>
    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>

    ②在shop-common模块的pom.xml中添加nacos的依赖

    1. <dependency>
    2. <groupId>com.alibaba.cloudgroupId>
    3. <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    4. dependency>

    ③ 在主类上添加@EnableDiscoveryClient注解

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

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

    因为小编是直接将三个微服务全都注册了,所以这里Nacos会显示三个列表

    4.2DiscoveryClient实现负载均衡

    接下来实现负载均衡的三种方式来了,首先是最原始的一种DiscoveryClient

    ①我们先使用idea赋值一个商品微服务

    ②通过nacos查看微服务的启动情况

    我们启动复制的微服务,那么shop-product也会在Nacos中注册多一个

     ③ 修改shop-order 的代码,实现负载均衡

    1. package com.zq.shoporder.controller;
    2. import com.zq.entity.Order;
    3. import com.zq.entity.Product;
    4. import com.zq.entity.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.web.bind.annotation.PathVariable;
    9. import org.springframework.web.bind.annotation.RequestMapping;
    10. import org.springframework.web.bind.annotation.RestController;
    11. import org.springframework.web.client.RestTemplate;
    12. import java.util.List;
    13. import java.util.Random;
    14. /**
    15. * @author张强
    16. * @site www.zq.com
    17. * @create  2022-11-25 15:35
    18. */
    19. @RequestMapping("/order")
    20. @RestController
    21. public class OrderController {
    22. @Autowired
    23. private RestTemplate restTemplate;
    24. @Autowired
    25. private DiscoveryClient discoveryClient;
    26. @RequestMapping("/get/{uid}/{pid}")
    27. public Order get(@PathVariable("uid") Integer uid,
    28. @PathVariable("pid") Integer pid){
    29. User user = restTemplate.getForObject("http://localhost:8070/user/get/" + uid, User.class);
    30. //从nacos中获取服务地址
    31. //自定义规则实现随机挑选服务
    32. List instances = discoveryClient.getInstances("shop-product");
    33. int index = new Random().nextInt(instances.size());
    34. ServiceInstance serviceInstance = instances.get(index);
    35. String url = serviceInstance.getHost() + ":" +
    36. serviceInstance.getPort();
    37. //通过restTemplate调用商品微服务
    38. Product product = restTemplate.getForObject("http://" + url +
    39. "/product/get/" + pid, Product.class);
    40. Order order = new Order();
    41. order.setNumber(2);
    42. order.setOid(System.currentTimeMillis());
    43. order.setPid(pid);
    44. order.setPname(product.getPname());
    45. order.setPprice(product.getPprice() * order.getNumber());
    46. order.setUid(user.getUid());
    47. order.setUsername(user.getUsername());
    48. return order;
    49. }
    50. }

      ④测试查看端口号每次访问是不是有不一样

    结果发现访问product 的微服务成功实现负载均衡!

    4.3Ribbon实现负载均衡

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

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

    @Bean@LoadBalancedpublic RestTemplate restTemplate() {    return new RestTemplate();}

    ②修改shop-order 的代码,实现负载均衡

    注意:

    1. package com.zq.shoporder.controller;
    2. import com.zq.entity.Order;
    3. import com.zq.entity.Product;
    4. import com.zq.entity.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张强
    12. * @site www.zq.com
    13. * @create  2022-11-25 15:35
    14. */
    15. @RequestMapping("/order")
    16. @RestController
    17. public class OrderController {
    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. String url = "shop-product";
    24. String url2 ="shop-user";
    25. User user = restTemplate.getForObject("http://"+url2+"/user/get/" + uid, User.class);
    26. //通过restTemplate调用商品微服务
    27. Product product = restTemplate.getForObject("http://"+url+"/user/get/" + pid, Product.class);
    28. Order order = new Order();
    29. order.setNumber(2);
    30. order.setOid(System.currentTimeMillis());
    31. order.setPid(pid);
    32. order.setPname(product.getPname());
    33. order.setPprice(product.getPprice() * order.getNumber());
    34. order.setUid(user.getUid());
    35. order.setUsername(user.getUsername());
    36. return order;
    37. }
    38. }

     4.4基于Feign实现负载均衡

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

    ①加入Fegin的依赖

    1. <dependency>
    2. <groupId>org.springframework.cloudgroupId>
    3. <artifactId>spring-cloud-starter-openfeignartifactId>
    4. dependency>

    ②在主类上添加Fegin的注解

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

    1. package com.zq.shoporder.service;
    2. import com.zq.entity.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. @FeignClient("shop-product")//声明调用的提供者的name
    7. public interface ProductService {
    8. //指定调用提供者的哪个方法
    9. //@FeignClient+@GetMapping 就是一个完整的请求路径
    10. //http://serviceproduct/product/{pid}
    11. @GetMapping(value = "/product/get/{pid}")
    12. Product findByPid(@PathVariable("pid") Integer pid);
    13. }

    ④修改controller代码,并启动验证

    1. package com.zq.shoporder.controller;
    2. import com.zq.entity.Order;
    3. import com.zq.entity.Product;
    4. import com.zq.entity.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张强
    12. * @site www.zq.com
    13. * @create  2022-11-25 15:35
    14. */
    15. @RequestMapping("/order")
    16. @RestController
    17. public class OrderController {
    18. @Autowired
    19. private RestTemplate restTemplate;
    20. @Autowired
    21. public ProductService productService;
    22. @RequestMapping("/get/{uid}/{pid}")
    23. public Order get(@PathVariable("uid") Integer uid,
    24. @PathVariable("pid") Integer pid){
    25. String url = "shop-product";
    26. String url2 ="shop-user";
    27. User user = restTemplate.getForObject("http://"+url2+"/user/get/" + uid, User.class);
    28. //通过restTemplate调用商品微服务
    29. Product product = productService.get(pid);
    30. Order order = new Order();
    31. order.setNumber(2);
    32. order.setOid(System.currentTimeMillis());
    33. order.setPid(pid);
    34. order.setPname(product.getPname());
    35. order.setPprice(product.getPprice() * order.getNumber());
    36. order.setUid(user.getUid());
    37. order.setUsername(user.getUsername());
    38. return order;
    39. }
    40. }

     4.5Feign参数传递

    在使用Feign用作服务注册时作为后台需要注意一下几点

    1. 基本数据类型参数需要带上@PathVariable("uid")注解
    2. 对象参数需要加上@RequestBody注释
    1. @RequestMapping("/findByParameter2")
    2. public String findByParameter2(
    3. @RequestParam("name") String name,
    4. @RequestParam("price") Double price){
    5. log.info("服务提供者日志:{},{}",name,price);
    6. return "hello:"+name+price;
    7. }
    8. @RequestMapping("/findByRequestBody")
    9. public Product findByRequestBody(@RequestBody Product product){
    10. log.info("服务提供者日志:{}",product.getPname());
    11. return product;
    12. }

  • 相关阅读:
    算法通过村第十八关-回溯|青铜笔记|什么叫回溯(中篇)
    Cocos Creator3.8 项目实战(五)背景无限滚屏效果如何实现
    安全关键软件开发与审定——DO-178C标准实践指南阅读笔记六——软件需求
    Arduino 拓展班DMP280的代码问题
    ubuntu 20.4下安装 npm 报错解决办法
    IP/SIP网络有源吸顶喇叭 20W扬声器 可供POE供电
    E. Speedrun
    PyScript:让Python在HTML中运行
    PSO粒子群优化算法
    【机器学习】最大期望算法(EM)
  • 原文地址:https://blog.csdn.net/weixin_66110079/article/details/128075963