环境搭建:idea2022、jdk8、springboot2.1.3、Mybatis plus、MySQL
案例搭建:以电商系统中常见的用户下单为例,用户向订单微服务发起一个购买的请求。在进行保存订单之前 需要调用商品微服务查询当前商品库存,单价等信息。在这种场景下,订单微服务就是一个服务消费者,商品微服务就是一个服务提供者
数据库表:shop_order订单表、shop_product商品表、shop_user用户表
服务模块:公共父模块springcloud_alibaba、公共模块 shop_common ,用于存放公共的实体类和工具类、订单微服务模块 shop_order 端口8091、商品微服务模块 shop_product 端口8081、用户微服务模块 shop_user 端口8071
案例基础代码可以从我的gitee公共仓库自行下载,请勿向主分支上传自己的代码https://gitee.com/aizqy/spring-cloud.git
RestTemplate:
环境基础搭建三个基础的微服务,在用户下单时需要调用商品微服务提供的HTTP接口获取商品数据,在此我们使用Spring框架提供的RestTemplate类。
此类可用于在应用中调用rest服务,它简化了与http服务的通信方式,统 一了RESTful的标准封装了http链接, 我们只需要传入url及返回值类型即可。相较于之前常用的HttpClient ,RestTemplate是一种更简洁优雅的调用RESTful服务的方式。
主要代码案例:
在shop_order工程中配置RestTemplate
//配置RestTemplate交给spring管理
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();}
在shop_order工程的控制器中调用商品微服务
//根据id查商品 方法+返回值类型
Product product = restTemplate.getForObject("http://localhost:8081/product/select/1",Product.class);
存在问题:代码灵活度基本为0,应用场景有局限,无法动态调整,此时就需要通过注册中心动态的对服务注册和服务发现,即我们接下来要了解到的微服务注册中心的一种:nacos
Nacos:
在认识nacos之前,我们先来了解微服务注册中心是什么?
微服务注册中心:
我们可以将微服务注册中心简单理解为服务于服务之间的“引导员”,它记录了服务与服务地址之间的映射关系。当一个服务需要调用另一个服务时,便可以在注册中心找到服务的地址进行调用。
主要作用:
服务注册中心是微服务架构非常重要的一个组件,在微服务架构里主要起到了协调者的一个作用
服务发现:
服务注册/反注册:保存服务提供者和服务调用者的信息
服务订阅/取消订阅:服务调用者订阅服务提供者的信息,最好有实时推送的功能
服务路由(可选):具有筛选整合服务提供者的能力
服务配置:
配置订阅:服务提供者和服务调用者订阅微服务相关的配置
配置下发:主动将配置推送给服务提供者和服务调用者
服务健康检测:
检测服务提供者的健康情况
nacos:
nacos的作用就是一个注册中心,用来管理注册上来的各个微服务
nacos简单实现:
1.从github下载安装nacos,点击startup.cmd运行后访问控制台
2.向商品与订单项目pom文件导入nacos依赖:
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
3.在启动类上添加@EnableDiscoveryClient注解
4.在yaml文件中添加nacos服务的地址
spring:
application:
name: service-order 服务调用标识
cloud:
nacos:
discovery:
server-addr: localhost:8848
5.启动order与product的启动类;登录nacos,查看服务列表是否有启动的微服务,登录名密码nacos
6.在shop_order工程的控制器中调用商品微服务,借助DiscoveryClient实现微服务调用
@Autowired
private DiscoveryClient discoveryClient;
//nacos实现
ServiceInstance instance = discoveryClient.getInstances("service-product").get(0);
String url = instance.getHost();
int post = instance.getPort();
根据id查商品 方法+返回值类型
Product product = restTemplate.getForObject("http://"+url+":"+post+"/product/select/" + pid,Product.class);
nacos隔离设计:
nacos中可以有多个namespace;namespace下可以有group;不同namespace之间相互隔离,例如不同namespace的服务互相不可见,在yaml文件中添加:
#将商品服务注册至dev命名空间下
spring:
application:
name: server-product
cloud:
nacos:
discovery:
server‐addr: 127.0.0.1:8848 # 注册中心地址
namespace: a1f8e863‐3117‐48c4‐9dd3‐e9ddc2af90a8 # 开发环境
cluster‐name: DEFAULT # 默认集群,可不填写
#注意相互依赖的服务,即有方法调用的服务必须在同一个命名空间下
在nacos控制台可以看到:
nacos配置管理:
当微服务的数量增多时,我们可以将微服务中的配置文件集中管理,步骤如下:
注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要
从nacos拉取配置:
1.引入nacos-config依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2.将原application.yaml修改为bootstrap.yaml,因为bootstrap的优先级高于application,项目启动时会先从bootstrap文件中读取到nacos的配置,从而得到全局配置,bootstrap中修改为:
spring:
application:
name: service-product
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #nacos中心地址
file-extension: yaml # 配置文件格式
profiles:
active: dev # 环境标识,开发环境
nacos热部署:
1.在nacos配置中心添加:
config:
appName: product
2.测试方法:在@Value注入的变量所在类上添加注解@RefreshScope:
@RestController
@RefreshScope//只需要在需要动态读取配置的类上添加此注解就可以
public class NacosConfigController {
@Value("${config.appName}")
private String appName;
@GetMapping("/nacos-config-test1")
public String nacosConfingTest1() {
return appName;
}
配置共享:
同服务内的配置共享:
1.在注册中心分别创建三个配置文件:spring.application.yaml(公共配置)、service-product-test.yaml、service-product-dev.yaml
2.将test与dev中重复的配置放入公共配置中,分别在test与dev中添加:
config:
env: test
config:
env: dev
3.测试:
@RestController
@RefreshScope
public class NacosConfigController {
@Value("${config.env}")
private String env;
//3 同一微服务的不同环境下共享配置
@GetMapping("/nacos-config-test3")
public String nacosConfingTest3() {
return env;
}
}
不同服务的配置共享:
1.在nacos配置中心创建公共配置文件all-service.yaml,将所有服务的公共配置放入,如同一数据库的连接
2.修改bootstrap.yaml:
spring:
application:
name: service-product
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #nacos中心地址
file-extension: yaml # 配置文件格式
shared-dataids: all-service.yaml # 配置要引入的配置
refreshable-dataids: all-service.yaml # 配置要实现动态配置刷新的配置
profiles:
active: dev # 环境标识
Ribbon:
经过nacos的学习,我们实现了服务的注册与发现,但是在服务之间如何更加方便的相互调用、高并发时如何负载均衡等任然存在问题。
Ribbon是 Netflixfa 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。SpringCloud 中,Nacos一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从Nacos中读取到的服务信息,在调用服务节点提供的服务时,会合理的进行负载;Ribbon自动的从注册中心中获取服务提供者的列表信息,并基于内置的负载均衡算法,请求服务
Ribbon主要作用:
服务调用:基于Ribbon实现服务调用, 是通过拉取到的所有服务列表组成(服务名-请求路径)映射关系借助RestTemplate 最终进行调用
负载均衡:当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址
Ribbon简单实现:
1.在创建RestTemplate方法 上添加 @LoadBalanced 注解
2.通过服务名称消费使用
//Ribbon实现
String url = "service-product";
Product product = restTemplate.getForObject("http://"+url+"/product/select/" + pid,Product.class);
Ribbon实现负载均衡:
负载均衡:在高并发场景下,我们需要多个服务器来处理请求,那么合理的为每个服务器分配任务即为负载均衡;按照实现位置可分为:服务器端负载均衡与客户端负载均衡
简单实现:
1.通过idea再启动一个 shop-product 微服务,设置其端口为8082
2.在yaml文件中添加配置:
#需要调用的微服务名称
service-product:
ribbon: #负载均衡策略
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
向上攀爬的痛苦,终会在登顶时烟消云散
——ZQY