SpringCloud复习01

SpringCloud复习01,第1张

此篇文章是在B站学习黑马SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式时所做的笔记。

文章目录
    • 认识微服务
    • 1.**微服务技术对比**
    • 2.SpringCloud
    • 3.服务拆分及远程调用
      • 3.1 服务拆分注意事项
      • 3.2 微服务远程调用
        • 3.2.1 远程调用方式分析
        • 3.2.2 提供者与消费者
    • 4.Eureka注册中心
      • 4.1 动手实践
        • 1) 搭建注册中心(搭建EurekaServer)
        • 2) 服务注册
        • 3) 服务发现
    • 5.负载均衡
      • 5.1 负载均衡原理
      • 5.2 源码跟踪
      • 5.3 负载均衡策略
      • 5.4 饥饿加载
    • 6.Nacos注册中心
      • 6.1 认识nacos
      • 6.2 注册服务到Nacos
      • 6.3 Nacos服务分级存储模型
      • 6.4 服务跨集群调用问题
      • 6.5 服务集群属性设置
      • 6.6 根据集群设置负载均衡优先级
      • 6.7 根据权重负载均衡
      • 6.8 环境隔离 - namespace
      • 6.9 Nacos与Eureka的区别

认识微服务

单体架构:将业务的所有功能都几种在一个项目开发,打成一个包部署;优点:架构简单,部署成本低;缺点:耦合度高。

分布式架构:根据业务功能进行拆分,每个业务模块作为独立项目开发,称为一个服务;优点:降低耦合,有利于服务升级扩展;缺点:架构复杂,难度大。

分布式架构要考虑的问题:

  • 服务拆分粒度如何?
  • 服务集群地址如何维护?
  • 服务直接如何实现远程调用?
  • 服务健康状态如何感知?

微服务:是一种良好的分布式架构方案。

微服务架构特征:

  • 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发

  • 面向服务:微服务对外暴露业务接口

  • 自治:团队独立、技术独立、数据独立、部署独立

  • 隔离性强:服务调用做好隔离、容错、降级,避免出现级联问题

微服务结构:

1.微服务技术对比

2.SpringCloud

SpringCloud是国内使用最广泛的微服务框架技术。官网:https://spring.io/projects/spring-cloud

SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配。

SpringCloud的组件:

3.服务拆分及远程调用 3.1 服务拆分注意事项
  1. 单一职责:不同微服务,不要重复开发相同业务

  2. 数据独立:不要访问其它微服务的数据库

  3. 面向服务:将自己的业务暴露为接口,供其它微服务调用

3.2 微服务远程调用 3.2.1 远程调用方式分析

首先浏览器发送请求到用户模块,用户模块在到数据库查询信息;这时候订单模块在发送请求到用户模块,用户模块在到数据库查询信息。

步骤:

  1. 在配置类中注册RestTemplate。(在启动类中也可以注册,因为启动类中的注解包含了@Configuration)
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
  1. 服务远程调用RestTemplate
package cn.itcast.order.service;

import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.net.URI;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);

        // 2.查询用户信息
        String url = "https://localhost:8081/user/" + order.getUserId();
        User user = restTemplate.getForObject(url, User.class); //Xxxx.class作用是把Json数据转换为Xxx.class这个类型的对象。

        // 3.把user赋值给order
        order.setUser(user);

        // 4.返回
        return order;
    }
}

总结:微服务调用方式

  • 基于RestTemplate发起的http请求实现远程调用。
  • http请求做远程调用是与语言物质的调用,只需要知道对方的ip、端口、接口路径、请求参数即可。
3.2.2 提供者与消费者
  • 服务提供者:一次业务中被其它微服务调用的。(提供接口给其它微服务使用)
  • 服务消费者:一次业务中调用其他微服务。(调用其他微服务的接口)

思考:服务A调用服务B,服务B调用服务C,那么服务B是什么绝色?

相对于A来说服务B是服务提供者;相对于服务C来说服务B是服务消费者。

总结:服务调用关系

  • 服务提供者:暴露接口给其它微服务调用。

  • 服务消费者:调用其它微服务提供的接口。

  • 提供者与消费者角色其实是相对的。

  • 一个服务可以同时是服务提供者和服务消费者。

4.Eureka注册中心

EureKa的作用

消费者该如何获取服务提供者具体信息?

  1. 服务提供者启动时向eureka注册自己的信息。

  2. eureka保存这些信息。

  3. 消费者根据服务名称向eureka拉取提供者信息。

如果有多个服务提供者,消费者该如何选择?

  1. 服务消费者利用负载均衡算法,从服务列表中挑选一个。

消费者如何感知服务提供者健康状态?

  1. 服务提供者会每隔30秒向EurekaServer发送心跳请求,报告健康状态。

  2. eureka会更新记录服务列表信息,心跳不正常会被剔除。

  3. 消费者就可以拉取到最新的信息。

4.1 动手实践 1) 搭建注册中心(搭建EurekaServer)

搭建EurekaServer服务步骤:

  1. 创建项目,引入注册中心依赖。
        
		<dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
        dependency>
  1. 编写启动类,添加@EnaleEurekaServer注解。
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class,args);
    }

}
  1. 添加application.yml文件,编写下面的配置:
server:
  port: 10086 # 服务端口

spring:
  application:
    name: eurekaserver  # eureka的服务名称
    
eureka:
  client:
    service-url:  # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka
2) 服务注册

将xxxService服务注册到EurekaServer步骤如下:

  1. 在要注册到EurekaServer的项目下引入eureka客户端依赖。
        
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>
  1. 在application.yml文件,编写下面的配置:
Spring:
  application:
    name: userservice  # user的服务名称
eureka:
  client:
    service-url: # eureka的地址信息
      defaultZone: http://127.0.0.1:10086/eureka
3) 服务发现

服务拉取(服务发现)是基于服务名称获取服务列表,如何在对服务列表做负载均衡。

  1. 修改url路径,用服务名代替ip、端口。

  2. 在启动类的RestTemplate添加负债均衡注解:

   @Bean
   @LoadBalanced  //负载均衡
   public RestTemplate restTemplate(){
       return new RestTemplate;
   }

总结

  1. 搭建注册中心

    • 引入注册中心依赖。
    • 在启动类上添加@EnaleEurekaServer注解。
    • 编写application.yml配置文件。
  2. 服务注册

    • 引入eureka-client依赖。
    • 编写application.yml配置文件。
    • 无论是消费者还是提供者,只要完成了上面两步都可以进行服务注册。
  3. 服务发现

    • 给RestTemplate添加@EnaleEurekaServer注解。
    • 用服务提供者的服务名称代替ip、端口号进行远程调用。
5.负载均衡

上面我们说到了注解@LoadBalanced可以实现负载均衡下面,我们来探讨一下它的原理。

5.1 负载均衡原理

SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。

那么我们发出的请求明明是http://userservice/user/1,怎么变成了http://localhost:8081的呢?

5.2 源码跟踪

为什么我们只输入了service名称就可以访问了呢?之前还要获取ip和端口。

显然有人帮我们根据service名称,获取到了服务实例的ip和端口。它就是LoadBalancerInterceptor,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

我们进行源码跟踪:

1)LoadBalancerIntercepor

可以看到这里的intercept方法,拦截了用户的HttpRequest请求,然后做了几件事:

  • request.getURI():获取请求uri,本例中就是 http://user-service/user/8
  • originalUri.getHost():获取uri路径的主机名,其实就是服务id,user-service
  • this.loadBalancer.execute():处理服务id,和用户请求。

这里的this.loadBalancerLoadBalancerClient类型,我们继续跟入。

2)LoadBalancerClient

继续跟入execute方法:

代码是这样的:

  • getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。
  • getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8082端口的服务

放行后,再次访问并跟踪,发现获取的是8081:

果然实现了负载均衡。

3)负载均衡策略IRule

在刚才的代码中,可以看到获取服务使通过一个getServer方法来做负载均衡:

我们继续跟入:

继续跟踪源码chooseServer方法,发现这么一段代码:

我们看看这个rule是谁:

这里的rule默认值是一个RoundRobinRule,看类的介绍:

这就是轮询的意思。

到这里,整个负载均衡的流程我们就清楚了。

4)总结

SpringCloudRibbon的底层采用了一个拦截器,拦截了RestTemplate发出的请求,对地址做了修改。用一幅图来总结一下:

基本流程如下:

  • 拦截我们的RestTemplate请求http://userservice/user/1
  • RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
  • DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
  • eureka返回列表,localhost:8081、localhost:8082
  • IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
  • RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求。
5.3 负载均衡策略

Ribbon的负载均衡规则是IRule接口来定义的,每一个实现类都是一种规则。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FWVT3RhE-1650854419191)(http://www.kaotop.com/file/tupian/20220427/favicon.ico)]

内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

修改负载均衡规则的两种方式

  1. 代码方式:在服务消费者的启动类上注入一个新的IRule。

        @Bean
        public IRule randomRule(){
            return new RandomRule();
        }
    
  2. 配置文件的方式:在服务消费者的application.yml文件上配置:

    # userservice这是服务的名称,自己设置的
    userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 
    

注意:一般情况下都是用默认的负载均衡规则。

5.4 饥饿加载

Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients: userservice # 指定对userservice这个服务饥饿加载
6.Nacos注册中心 6.1 认识nacos

Nacos是阿里巴巴的产品,现在是SpringCloud中的一个组件。功能比Eureka多,在国内受欢迎程度高。

在bin目录下运行指令:startup.cmd -m standalone 启动Nacos

6.2 注册服务到Nacos
  1. 在父工程中添加Nacos依赖管理:

                
                <dependency>
                    <groupId>com.alibaba.cloudgroupId>
                    <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                    <version>2.2.6.RELEASEversion>
                    <type>pomtype>
                    <scope>importscope>
                dependency>
    
  2. 需要注释掉原有的eureka依赖。

  3. 添加Nacos的客户端依赖:

    
            
            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
            dependency>
    
  4. 修改服务消费者和服务提供者中的application.yml文件,注释掉eureka地址,添加Nacos地址。

spring:
  application:
    name: orderservice  # order的服务名称
  cloud:
    nacos:
      server-addr: localhost:8848   # nacos 服务地址
  1. 启动并测试

启动后在浏览器输出: http://10.50.58.199:8848/nacos/index.html

6.3 Nacos服务分级存储模型
  • 一级是服务
  • 二级是集群
  • 三级是实例

6.4 服务跨集群调用问题
  1. 服务调用时尽可能选择本地集群的服务,因为跨集群调用延迟较高。
  2. 本地集群不可访问时,再去访问其它集群。

6.5 服务集群属性设置
  1. 在application.yml文件下设置集群名称:
spring:
  application:
    name: orderservice  # order的服务名称
  cloud:
    nacos:
      server-addr: localhost:8848   # nacos 服务地址
	  discovery:
        cluster-name: GZ   # 配置集群名称,也就是机房位置。
6.6 根据集群设置负载均衡优先级
  1. 修改服务消费者中的application.yml配置:

    spring:
      cloud:
        nacos:
          server-addr: localhost:8848   # nacos 服务地址
          discovery:
            cluster-name: HZ   # 配置集群名称,也就是机房位置。
    
  2. 然后在服务消费者中设置负载均衡的IRule为NacosRule。

userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则

NacosRule负载均衡策略:这个规则会优先寻找与自己同集群的服务;找不到才会去其他的集群找,而且日志会发出警告;确定了集群后,在采用随机的方式选择实例。

6.7 根据权重负载均衡

在实际部署当中会出现这样的情况:

  • 企业里服务器设备会更新迭代,有些服务器性能比较好,有些服务器性能比较差,而我们希望性能好的机器承担更多的用户请求。

Nacos提供了权重配置来控制访问频率,权重越大则访问率越高;我们就可以把性能好的机器权重设高一些,性能差的机器权重设小写。

可以在Nacos控制台设置权重值,权重值在0~1之间,权重值越大被访问的频率就越高。

权重值设置为0将完全不能被访问。

6.8 环境隔离 - namespace

Nacos中服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离。

  1. 可以在控制台中创建namespace,用来隔离不同环境
  2. 填写命名空间和描述
  1. 然后会在Nacos控制台看到命名空间名称和命名空间ID

  1. 修改服务消费者的application.yml,添加namespace:
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?characterEncoding=utf-8&serverTimezone=UTC
    username: root
    password: abc123
    driver-class-name: com.mysql.cj.jdbc.Driver
  application:
    name: orderservice  # order的服务名称
  cloud:
    nacos:
      server-addr: localhost:8848   # nacos 服务地址
      discovery:
        cluster-name: HZ   # 配置集群名称,也就是机房位置。
        namespace: 011dadf0-ae68-48f9-a2b7-e9d8ca809376   # 命名空间,填ID
  1. 重启order-server后

  1. 此时访问order-server后,因为namespace不同,会导致找不到user-server然后报错。

每个namespace都有唯一;服务在application.yml文件所在是写的是id不是空间名称;不同namespace下的服务相互不可见。

6.9 Nacos与Eureka的区别

Nacos的服务实例分为两种类型,临时实例和非临时实例

临时实例宕机时,会从nacos的服务列表中剔除,而非临时实例则不会。

  • Nacos与eureka的共同点

    • 都支持服务注册和服务拉取
    • 都支持服务提供者心跳方式做健康检测
  • Nacos与Eureka的区别

    • Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式
    • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除
    • Nacos支持服务列表变更的消息推送模式,服务列表更新更及时
    • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

SpringCloud复习02

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/741934.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-28
下一篇 2022-04-28

发表评论

登录后才能评论

评论列表(0条)

保存