第四阶段微服务

本文详细介绍了Spring Cloud Alibaba微服务架构,包括核心组件Nacos的注册与服务发现、服务调用分析、Feign远程服务调用、配置中心、限流降级策略、Sentinel的使用等。讲解了服务注册、服务调用、负载均衡、服务降级、熔断、Feign的声明式服务调用、配置管理以及Sentinel的限流和降级规则,涉及Spring Cloud Gateway的路由设计和过滤器。最后讨论了单点登录系统的实现,包括JWT令牌的颁发与解析、权限校验等。
摘要由CSDN通过智能技术生成

什么是微服务:

微服务架构(MSA)是将单个应用程序开发为一组独立服务,在自己的进程中运行,独立开发和部署

在这里插入图片描述

 每个服务都是一个功能,都是独立运行,更新,部署和扩展不会影响到别的服务,

总结:

1.每个服务都有自己独立空间.开发,更新,部署和扩展不会影响的别的服务

2.就是将各个服务之间的共性进行抽取,形成独立的服务.

3.微服务就是一种架构方式,架构中的每个服务(service)都是按照一定的业务设计的,并且都是用来解决问题的.

在这里插入图片描述

 Alibaba 解决方案(掌握)

降级从专业的维度讲,就是熔断,就是当负荷比较大时,关闭一些服务.比方说电流太大,跳闸了,

核心组件分析
Spring Cloud Alibaba 默认提供了如下核心功能(先了解):

服务限流降级:
默认支持 WebServlet、OpenFeign、RestTemplate、Spring Cloud Gateway, RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
服务注册与发现:
基于Spring Cloud 服务注册与发现标准,借助Nacos进行实现,默认还集成了 Ribbon 的支持。
分布式配置管理:
基于Nacos支持分布式系统中的外部化配置,配置更改时自动刷新。
消息驱动能力:
基于Spring Cloud Stream 为微服务应用构建消息驱动能力。
分布式事务:
使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。。
分布式任务调度:
提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker上执行。

Nacos注册中心简介

就是如何在不同的服务之间进行通信?如何更好更方便的管理应用中的每一个服务,如何建立各个服务之间联系的纽带,由此注册中心诞生(例如淘宝网卖家提供服务,买家调用服务)。

我们如何进行选型呢?我们主要从社区活跃度,稳定性,功能,性能等方面进行考虑即可

官网:https://nacos.io/zh-cn/docs/quick-start.html

服务注册与调用入门(重点)

1.创建两个项目分别为服务提供者和服务消费者,两者都要注册到NacosServer中,

这个server本质上就是一个web服务,端口默认为8848),然后服务提供者可以为服务消费者提供远端调用服务(例如支付服务为服务提供方,订单服务为服务消费方.

在这里插入图片描述

打包:

1.deploy:在本地库存一份,上传远程仓库.

2.package:生成jar文件.

3.install:生成Jsr包,在本地库存一份

 

解决方案架构设计

基于Spring Cloud Alibaba实现的微服务,

在这里插入图片描述

项目结构分析:(聚合工程)

在这里插入图片描述

总结:

1.父工程主要提供版本和依赖.

2.服务方和提供方是具体业务需求.

3.订单服务消耗商品服务

4.父工程管理所有子工程,消费方通过购买服务来调用提供方,Nacos可以看到每一条信息.

5.每一个单独的服务,都是一组小型程序,通过调用来获取服务

 服务调用分析

在这里插入图片描述

总结:

1.不同的服务有不同的IP地址和端口号

2.前面还有网关还没有讲.统一访问的路口

3.现在是服务带服务要明白.(是内部服务的调用),

4.外部直接访问

负载均衡方式的调用:

方式一:性能好,代码多

   第一步: 服务调用 RestTemplate
    @Bean 
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

        第二步:调用配置文件名字必须保持一致.
        @Value("${spring.application.name}")
        private String appName;

     第三步:   
    @GetMapping("/consumer/doRestEcho2")
        public String doRestEcho2(){
            基于loadBalancerClient方式获取服务实例
            String serviceId="sca-provider";//这个名字要在nacos的服务列表中
            ServiceInstance choose = loadBalancerClient.choose(serviceId);
            String ip=choose.getHost();
            int port=choose.getPort();
            String url=String.format("http://%s:%s/provider/echo/%s",ip,port,appName);
            return restTemplate.getForObject(url,String.class);
        }

@LoadBalanced:

  • @LoadBalanced的作用是什么?(描述RestTemplate对象,用于告诉Spring框架,在使用RestTempalte进行服务调用时,这个调用过程会被一个拦截器进行拦截,然后在拦截器内部,启动负载均衡策略。)

方式二:性能差,代码少

    @Bean
    @LoadBalanced //这个注解描述RestTemplate对象时,系统底层会对RestTemplate对象的请求进行拦截
    public RestTemplate loadBalanceRestTemplate(){
        return new RestTemplate();
    }

        @Autowired
        private RestTemplate loadBalanceRestTemplate;
        //负载均衡客户端对象(基于此对象可以从nacos中获取服务列表,并且可以基于一定的算法
        //从列表中获取一个服务实例)

        //负载均衡应用方式2:@LoadBalance
        @GetMapping("/consumer/doRestEcho3")
        public String doRestEcho3(){
            String serviceId="sca-provider";
            String url=String.format("http://%s/provider/echo/%s",serviceId,appName);
            return loadBalanceRestTemplate.getForObject(url,String.class);
        }

方式三:动态接收

 @GetMapping("/consumer/doRestEcho1")
        public String doRestEcho1(){
//            String url = "http://localhost:8081/provider/echo/"+appName;
//            return restTemplate.getForObject(url,String.class);
            String serverId="sca-provider";
            ServiceInstance choose = loadBalancerClient.choose(serverId);
            String ip=choose.getHost();
            int port = choose.getPort();
           // String url = "http://"+ip+":"+port+"/provider/echo/"+appName;
            String url = String.format("http://%s:%s/provider/echo/%s",ip,port,appName);
            return restTemplate.getForObject(url,String.class);

了解:手动随机负载均衡:

思考题:

创建RestTemplate对象,然后基于此对象进行远程服务调用
 @Bean 注解用于描述方法,用于告诉spring框架这个方法的返回值交给spring管理,
 spring默认会这个方法返回对象起一个bean的名字(key),默认为方法名.当然也可以
 对一个bean的名字进行自定义,例如@Bean("自己定义的名字").
 思考:spring框架中为什么会给出这样的注解,用于描述方法,在方法中构建对象?
 第一:Spring是一个资源整合框架.
 第二:何为资源?(内存中对象)
 第三:所有对象是否都有类型?
 第四:所有对象的类型都是你自己定义的吗?不一定(有自己,有第三方)
 第五:第三方的类,我们能在类上直接添加注解描述吗(例如@Component)?不可以
@Autowired注解描述属性时,会告诉spring框架,要优先按属性类型进行对象的查找和注入,假如
此类型的对象存在多个,此时还会按照属性名进行查找和比对,有相同的则直接注入(DI),没有相同
的则出错,当然也可以在属性上添加@Qualifier("bean的名字")注解,指定要注入的具体对象

注意:以后工作中可能注解中加("msg")是因为兼容JDK1.8之前的版本

 消费方调用提供方的两种方式:一种不带参数, 一种带参数

 总结:

1.写法不友好,不够灵活,太死了.

2.不支持负载均衡

底层:

1.用到的组件HttpClient对象

2.OKHTTP

3.这种服务远程调用的过程进行了一种封装

@Bean

public RestTemplate restTemplate()

{ return new RestTemplate(); }


@Autowired

private RestTemplate restTemplate;

并发运行:

 小节面试分析(Nacos)

1.为什么要将服务注册到nacos?  (因为查找服务方便)

2.在Nacos中服务提供者是如何向Nacos注册中心(Registry)续约的?(5秒心跳)

任务调度.

3.对于Nacos服务来讲它是如何判定服务实例的状态?(检测心跳包,15,30)

3.服务启动时如何找到服务启 动注册配置类?(NacosNamingService)

底层(从这里看)

4.服务消费方是如何调用服务提供方的服务的?(RestTemplate)

小节面试分析

  • @Bean注解的作用?(一般用于配置类内部,描述相关方法,用于告诉spring此方法的返回值要交给spring管理,bean的名字默认为方法名,假如需要指定名字可以@Bean(“bean的名字”),最多的应用场景是整合第三方的资源-对象)
  • @Autowired注解的作用?(此注解用于描述属性,构造方法,set方法等,用于告诉spring框架,按找一定的规则为属性进行DI操作,默认按属性,方法参数类型查找对应的对象,假如只找到一个,则直接注入,类型多个时还会按照属性名或方法参数名进行值的注入,假如名字也不同,就出报错.)
  • Nacos中的负责均衡底层是如何实现的?(通过Ribbon实现,Ribbon中定义了一些负载均衡算法,然后基于这些算法从服务实例中获取一个实例为消费方法提供服务)
  • Ribbon 是什么?(Netflix公司提供的负载均衡客户端,一般应用于服务的消费方法)
  • Ribbon 可以解决什么问题? (基于负载均衡策略进行服务调用, 所有策略都会实现IRule接口)
  • Ribbon 内置的负载策略都有哪些?(8种,可以通过查看IRule接口的实现类进行分析)
  • @LoadBalanced的作用是什么?(描述RestTemplate对象,用于告诉Spring框架,在使用RestTempalte进行服务调用时,这个调用过程会被一个拦截器进行拦截,然后在拦截器内部,启动负载均衡策略。)
  • 我们可以自己定义负载均衡策略吗?(可以,基于IRule接口进行策略定义,也可以参考NacosRule进行实现)

基于Feign的远程服务调用

服务消费方基于rest方式请求服务提供方的服务时,一种直接的方式就是自己拼接url,拼接参数然后实现服务调用,但每次服务调用都需要这样拼接,代码量复杂且不易维护,此时Feign诞生

Feign是什么(一套组件)

Feign 是一种声明式Web服务客户端,底层封装了对Rest技术的应用,通过Feign可以简化服务消费方对远程服务提供方法的调用实现

在这里插入图片描述

 Feign应用实践

1.在消费方,添加项目依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2.启动类上添加@EnableFeignClients注解,用于告诉springboot在启动时,扫描启动类所在包或子包中的类,假如接口上有@FeignClient注解描述,则对这样的接口创建其实现类,在实现类内部帮我们进行远程服务调用

3.定义Http请求API,基于此API借助OpenFeign访问远端服务,

说明:假如@FeignClient注解中添加了contextId属性,则这个属性值默认
     会作为当前bean对象的名字,此时name的值仅仅作为要调用的服务名对待,一般
     推荐contextId的值默认为@FeignClient注解描述的接口的名字(首字母小写)

@FeignClient(name="sca-provider" ,
             contextId = "remoteProvideService")//sca-provider为服务提供者名称
interface RemoteProviderService{
    //@GetMapping表示以get请求方式调用远端服务
    //"/provider/echo/{msg}"为远程调用服务的url
    @GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
    public String echoMessage(@PathVariable("string") String string);
}
3.1)@FeignClient(name="sca-provider")//sca-provider为服务提供者名称,

3.2)用于描述远程调用接口.这个接口不需要你写实现类,你只需要定义访问规则即可(例如请求方式,请求url,请求参数).

网络不好使配置 

当我们在进行远程服务调用时,假如调用的服务突然不可用了或者调用过程超时了.

第一步:定义FallbackFactory接口的实现

 第二步:在Feign访问接口中应用FallbackFactory对象,

第三步:在配置文件application.yml中添加如下配置,启动feign方式调用时的服务中断处理机制.

Feign 调用过程分析(了解)

Feign应用过程分析(底层逻辑先了解):
1)通过 @EnableFeignCleints 注解告诉springcloud,启动 Feign Starter 组件。
2) Feign Starter 在项目启动过程中注册全局配置,扫描包下所由@FeignClient注解描述的接口,然后由系统底层创建接口实现类(JDK代理类),并构建类的对象,然后交给spring管理(注册 IOC 容器)。
3) 接口被调用时被动态代理类逻辑拦截,将 @FeignClient 请求信息通过编码器生成 Request对象,基于此对象进行远程过程调用。
4) 请求对象经Ribbon进行负载均衡,挑选出一个健康的 Server 实例(instance)。
5) 通过 Client 携带 Request 调用远端服务返回请求响应。
6) 通过解码器生成 Response 返回客户端,将信息流解析成为接口返回数据。

小节面试分析

  • 为什么使用feign?(基于Feign可以更加友好的实现服务调用,简化服务消费方对服务提供方方法的调用)。
  • @FeignClient注解的作用是什么?(告诉Feign Starter,在项目启动时,为此注解描述的接口创建实现类-代理类)
  • Feign方式的调用,底层负载均衡是如何实现的?(Ribbon)
  • @EnableFeignCleints 注解的作用是什么?(描述配置类,例如启动类)

图解服务调用方案

在这里插入图片描述

这张图描述了远程服务调用的几中方式:
第一种:服务比较少,例如就两个服务,一个服务消费,一个服务提供,就不需要注册中心,不需要负载均衡.
第二种:并发比较大,服务服务比较多,我们需要管理服务,就需要注册中心,我们还需要服务间的负载均衡.但代码编写的复杂多相对高一些,我们需要自己获取ip,获取端口,拼接字符串等.
第三种:我们要基于第二种进行代码简化,底层提供了一种拦截器,把基于服务名获取服务实例的过程在拦截器中做了封装,简化了代码的开发.但是加了拦截器多少会在性能少有一点损耗.
第四种方式主要是从代码结构上做一个挑战,我们前面三种基于RestTemplate进行服务调用,本身属于一种远程服务调用业务,能够将这种业务写到一个业务对象中,Feign方式就诞生了,它主要对代码结构的一种优化.

FAQ分析

  • Nacos是什么,提供了什么特性(服务的注册、发现、配置)?
  • 你为什么会选择Nacos?(活跃度、稳定、性能、学习成本)
  • Nacos的官网?(nacos.io)
  • Nacos在github的源码?(github.com/alibaba/nacos)
  • Nacos在windows环境下安装?(解压即可使用)
  • Nacos在windows中的的初步配置?(application.properties访问数据库的数据源)
  • Nacos服务注册的基本过程?(服务启动时发送web请求)
  • Nacos服务消费的基本过程?(服务启动时获取服务实例,然后调用服务)
  • Nacos服务负载均衡逻辑及设计实现?(Ribbon)
  • 注册中心的核心数据是什么?(服务的名字和它对应的网络地址)
  • 注册中心中心核心数据的存取为什么会采用读写锁?(底层安全和性能)
  • Nacos健康检查的方式?(基于心跳包机制进行实现)
  • Nacos是如何保证高可用的?(重试,本地缓存、集群)
  • Feign是什么,它的应用是怎样的,feign应用过程中的代理对象是如何创建的(JDK)?
  • Feign方式的调用过程,其负载均衡是如何实现?(Ribbon)

 门面设计模式+简单工厂模式:

简单工厂模式:通过类名调用静态方法,通过静态方法返回日志对象.

    创建java中的日志对象(SLF4J是java中的日志规范,是日志对外的窗口,是门面)
    目前市场上对SLF4J规范的实现主要有两种:log4j,logback
    private static final Logger log=
    LoggerFactory.getLogger(ProviderController.class);

配置中心简介:

  • 什么是配置中心?(存储项目配置信息的一个服务)
  • 为什么要使用配置中心?(集中管理配置信息,动态发布配置信息)
  • 市场上有哪些主流的配置中心?(Apollo,nacos,……)

日志级别trace<debug<info<warn<error

           
            log.trace("==log.trace==");//跟踪
            log.debug("==log.debug==");//调试
            log.info("==log.info==");//常规信息
            log.warn("==log.warn==");//警告
            log.error("==log.error==");//错误信息

Nacos配置:

第一步:添加依赖

  <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  </dependency>

修改配置文件:

将项目中的application.yml的名字修改为bootstrap.yml配置文件(启动优先级最高)

在这里插入图片描述

这个注解描述类时,当配置中心数据发生变化会对属性进行重新初始化

@RefreshScope

小节面试分析:

1.配置中心一般都会配置什么内容?(可能会经常变化的配置信息,例如连接池,日志、线程池、限流熔断规则)
2.什么信息一般不会写到配置中心?(服务端口,服务名,服务的注册地址,配置中心)
3.项目中为什么要定义bootstrap.yml文件?(此文件被读取的优先级比较高,可以在服务启动时读取配置中心的数据)
4.Nacos配置中心宕机了,我们的服务还可以读取到配置信息吗?(可以从内存,客户端获取了配置中心的配置信息以后,会将配置信息在本地内存中存储一份.)
5.微服务应用中我们的客户端如何获取配置中心的信息?(我们的服务一般首先会从内存读取配置信息,同时我们的微服务还可以定时向nacos配置中心发请求拉取(pull)更新的配置信息)

在1.4.2之前这种拉取是长轮循

段轮循:拉取去没有就回来,

长轮循:拉取去等29.5秒,没有就回来,因为30秒在拉取
在这里插入图片描述

6.微服务应用中客户端如何感知配置中心数据变化?(当数据发生变化时,nacos找到它维护的客户端,然后通知客户端去获取更新的数据,客户端获取数据以后更新本地内存,并在下次访问资源时,刷新@Value注解描述的属性值,但是需要借助@RefreshScope注解对属性所在的类进行描述)
服务启动后没有从配置中心获取我们的配置数据是什么原因?(依赖,配置文件名字bootstrap.yml,配置中心的dataId名字是否正确,分组是否正确,配置的名字是否正确,缩进关系是否正确,假如是动态发布,类上是否有@RefreshScope注解)
7.你项目中使用的日志规范是什么?(SLF4J)
8.你了解项目中的日志级别吗?(debug,info,error,…,可以基于日志级别控制日志的输出)
 

Nacos配置管理模型

在这里插入图片描述

在这里插入图片描述

  • Namespace:命名空间,对不同的环境进⾏隔离,⽐如隔离开发环境和⽣产环境。
  • Group:分组,将若⼲个服务或者若⼲个配置集归为⼀组。
  • Service/DataId:某⼀个服务或配置集,一般对应一个配置文件。
 config:    #配置中心的配置
        server-addr: localhost:8848
        file-extension: yml
        访问不一样的命名空间/组/ID
        namespace: 594e1efc-cd0a-43cf-9d35-2b6567d8b122

Nacos配置中心模型

在这里插入图片描述

        享元模式:(Flyweight Pattern)主要用于减少创建对象的数量,以减少内存占用和提高性能

        1.池也是减少对象的创建,让对象重性好,都会用这个模式.

Tomcat 请求处理分析

在这里插入图片描述

 分组设计及实现

当我们在指定命名空间下,按环境或服务做好了配置以后,有时还需要基于服务做分组配置,例如,一个服务在不同时间节点(节假日,活动等)切换不同的配置,可以在新建配置时指定分组名称

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值