spring Cloud项目总结

2022/4/8

cloud开始

建父pom项目,主要用来控制依赖版本
父项目的pom文件中的 pom
为pom,
其次,pom文件中的dependencyManagement标签,使用dependencyManagement可以统一管理项目的版本号,确保应用的各个项目的依赖和版本一致,不用每个模块项目都弄一个版本号,不利于管理,当需要变更版本号的时候只需要在父类容器里更新,不需要任何一个子项目的修改;如果某个子项目需要另外一个特殊的版本号时,只需要在自己的模块dependencies中声明一个版本号即可。子类就会使用子类声明的版本号,不继承于父类版本号。

 其次,dependencyManagement中依赖并没有导入,只是申明了版本号,真正的导入需要在子项目中

2.做项目的步骤
(1):建model
(2) : 改pom
(3) : 写yml
(4) : 主启动
(5) : 业务类

3.注意事项
1.实体类需要继承Serializable(序列化接口)

2.在mapper的xml文件中,插入方法需要多写两个参keyProperty=“id” useGeneratedKeys=“true”
分别是这两个,第一个代表主键名字,第二个表示返回的值
具体作用

3.Lombok注解失效的问题
在写子项目时,因为注解失效一直报错,但是导入的
@Data注解却没有问题,因为Lombok需要依赖和插件配合使用,我去查看了Lombok插件是ok的,
最后发现是版本兼容问题,Lombok插件在0.27版本之后需要使用1.18.8以上的Lombok依赖,
我自己的现在是0.32版本,使用1.18.8也没有用,最后去找了最新版本1.18.20,注解才生效

4.在写mapper的xml文件时,在写具体的方法时,当返回值是一个类的时候,最好使用使用resultMap,避免当字段复杂时,字段不匹配的情况,如图

 <resultMap id="payment" type="com.atguigu.springcloud.entities.payment">
        <id column="id" property="id" />
        <result column="serial" property="serial" jdbcType="VARCHAR"/>
    resultMap>

4.错误
1.在设置端口号时
将server写成了service导致设置的端口号失效了,而且port写成了post
正确写法

server:
  port: 8001

2.在设置mybatis的mapper文件位置时

mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.atguigu.springcloud.entities

正确的应该是上面的,我错误的把classpath的c大写了,导致mybatis找不到mapper文件

2022/4/9

注册中心

项目重构
因为在每个微服务中可能都需要使用到某个实体类或者工具类,为了使代码不重复,我们将重复的的地方提取出来,建成一个内部项目,放到maven上,需要的项目就直接导入就好了,例如
spring Cloud项目总结_第1张图片其他项目需要使用时,直接导入依赖即可

<dependency>
            <groupId>org.examplegroupId>
            <artifactId>cloud-api-commonsartifactId>
            <version>1.0-SNAPSHOTversion>
            <scope>compilescope>
        dependency>

注册中心
首先对注册中心的个人理解:
因为spring cloud有许多微服务的提供比如(支付模块,订单模块)。
服务注册中心的作用就是提供服务的信息的访问地址,客户端就可以通过服务注册中心去调用需要的服务。
注册中心是服务发现的核心。它保存了各个可用服务实例的网络地址(IP Address和Port)。服务注册中心必须要有高可用性和实时更新功能

1. eureka注册中心

在2018年停更,但是要了解他的原理。

微服务通过eureka服务端进行注册,客户端将需要的服务通过服务端找到对应服务的网络地址。

eureka集群
假若这个eureka服务端发生故障,就会导致整个系统发生问题,所以我们需要做eureka集群,即存在多个eureka服务端,相互注册,这样其中一个发生问题,不会导致整个系统发生问题。

负载均衡
负载均衡,就是将负载,均衡的分布,不能让客户端全部访问同一个服务的同一个机器,因为相同的微服务可能有10个,在10台机器上运行,但是eureka可以将整个这个服务看成一个整体,当客户端访问时,可以轮询将客户端的访问分布到每一个机器,这样不会导致某一台负载过大,(通俗的说,就是比如有1w个人在拼夕夕买东西,同时拼夕夕的支付模块同时有100个微服务在同时运行,负载均衡就是将这1w个人的支付请求分布到这100个微服务上,避免这1w个人同时访问某一个微服务。

使用eureka

首先要使用eureka,首先需要导入依赖,在eureka 2.X版本之后,依赖相对于第一版有了区别在依赖名字上直接可以分别出来。

eureka服务端
(1):建model
(2): 导入依赖

<dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
        dependency>

(3):写yml

server:
  port: 7003

eureka:
  instance:
    hostname: eureka7003.com
  #    hostname: eureka7001.com #eureka服务端的实例名称
  client:
    register-with-eureka: false     #false表示不向注册中心注册自己。
    fetch-registry: false     #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    service-url:
      #集群指向其它eureka
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
      #单机就是7001自己
    #      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/



    #server:
    #关闭自我保护机制,保证不可用服务被及时踢除
    #enable-self-preservation: false
    #eviction-interval-timer-in-ms: 2000

这里的eureka.instance.hostname=eureka7003.com是eureka服务端的ip地址,微服务需要注册时通过IP加端口可以进行注册。

(4):主启动
在eureka服务端上主函数上要用@EnableEurekaServer进行注解

@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7002 {
    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7002.class,args);
    }
}
service-url:
      defaultZone:

这里当需要做eureka集群时,每个eureka需要互相注册,即在后面加上需要注册的服务器URL,不需要做集群时就放自己的url就行了。

微服务端(服务端)

(1):建model

(2):改pom
需要导入以下依赖,与服务端不同是是,名字后面改成了eureka-client。

<dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
    dependency>

(3):写yml

server:
  port: 8000
spring:
  application:
    name: cloud-order-service
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true。
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetchRegistry: true
    service-url:
      #单机版
#      defaultZone: http://localhost:7001/eureka
      # 集群版
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
#  instance:
#    instance-id: payment8001
#    #访问路径可以显示IP地址
#    prefer-ip-address: true
#    #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
#    #lease-renewal-interval-in-seconds: 1
#    #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
#    #lease-expiration-duration-in-seconds: 2


将自己注册进eureka服务端。

defaultZone: 
http://eureka7001.com:7001/eureka,
http://eureka7002.com:7002/eureka,
http://eureka7003.com:7003/eureka

这里表示将自己注册到eureka集群中,即每个eureka服务端。
其中spring: application: name: cloud-order-service=cloud-order-service

cloud-order-service表示自己注册在eureeka服务端的名字
(4): 主启动
微服务需要注册到eureka服务端的每个微服务启动类上需要有

@EnableEurekaClient注解


@SpringBootApplication
@EnableEurekaClient
public class orderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(orderMain80.class,args);
    }
}

使用负载均衡
项目结构图
spring Cloud项目总结_第2张图片项目中7001,7002,7003这里是eureka集群,
8001,8002都是支付模块微服务提供者,8000是客户端。
其中8000注册在eureka服务端的名字是cloud-order-service
8001和8002的名字为cloud-provider-service
负载均衡即是将8000的访问分布到8001,8002两个支付模块上。
如图
spring Cloud项目总结_第3张图片在没有使用eureka时,8000是没有通过eureka直接使用RestTemplate与服务提供端进行连接的。

但是我们使用了eureka,这里我们将访问地址设置成微服务注册在eureka上的名字CLOUD-PROVIDER-SERVICE,然后在

@Configuration
public class webAppConfig implements WebMvcConfigurer {

    @Bean
    @LoadBalanced  //通过LoadBalanced注解赋予了RestTemplate负载均衡的能力
    public RestTemplate   getRestTemplate(){
        return new RestTemplate();
    }
}

配置类上,通过LoadBalanced注解赋予了RestTemplate负载均衡的能力,然后我们用客户端使用支付模块时,eureka会轮询的请求放到每个服务上。

eureka的自我保护机制

默认开启,即注册在eureka服务端的微服务, 微服务正常情况下每30s(默认)需要向服务端发送心跳包,表示自己还存在,保护机制即当微服务因为网络堵塞导致没有在30s内发送心跳包时,不会立即移除这个注册的微服务,
而是等待90s(默认)之后才移除,这样就保证了不会因为网络等其他原因移除了健康的服务。
在eureka服务端可以关闭,在yml的eureka:下面的client:下面加入

  #server:
#关闭自我保护机制,保证不可用服务被及时踢除
#enable-self-preservation: false
#eviction-interval-timer-in-ms: 2000

可以关闭自我保护,这里将90s改为2s,即当2秒没有收到微服务端的心跳包就移除微服务,这里还需要设置一下微服务端发送心跳包的时间

 #Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
      lease-renewal-interval-in-seconds: 1
#    #Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
      lease-expiration-duration-in-seconds: 2

这样就关闭了自我保护机制。

eureka前端显示问题
在这里插入图片描述
这里的payment8001与8002,本来是主机名的,通过yml文件的eureka下添加

instance:
    instance-id: payment8002
#    #访问路径可以显示IP地址
    prefer-ip-address: true

访问路径显示IP即在左下角可以显示IP
spring Cloud项目总结_第4张图片

使用zookeeper

首先安装zookeeper,我在云服务器上安装了zookeeper,安装步骤

安装完成后在bin下
./zkCli.sh 启动zookeeper
需要注意的是安装的zookeeper版本与导入依赖版本的兼容问题,这里我的zookeeper安装版本是3.7,依赖版本是3.0.5

微服务端
(1): 建model

(2): 改pom
zookeeper的依赖是这个

<dependency>
   <groupId>org.springframework.cloudgroupId>
   <artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
   <version>3.0.5version>
dependency>

(3):写yml

server:
  port: 8003

spring:
  application:
    name: cloud-provider-service
  cloud:
    zookeeper:
      connect-string: xxx.x.xxx.xxx:2181

这里的绑定zookeeper打开的端口,我这里是公网ip加2181端口。
(4)主启动

@SpringBootApplication
@EnableDiscoveryClient //该注解用于向注册中心注册服务(当注册中心使用zookeeper或者consul时)
public class paymentMain8003 {
    public static void main(String[] args) {
        SpringApplication.run(paymentMain8003.class,args);
    }
}

这里的@EnableDiscoveryClient并不是cookeeper特有的,而是spring cloud用来向注册中心注册的。

消费端
(1):建model

(2):改pom

<dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
            <version>3.0.5version>
        dependency>

(3)写yml

server:
  port: 8000

spring:
  application:
    name: cloud-consumer-order

  cloud:
    zookeeper:
      connect-string: 121.5.199.228:2181

(4)主启动

@SpringBootApplication
@EnableDiscoveryClient
public class consumerOrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(consumerOrderMain80.class,args);
    }
}

(5)业务类
配置类
这里需要在config类中在注入RestTemplate时,同样要加**@LoadBalanced** ,这个注解也是spring cloud提供的

@Configuration
public class webConfig implements WebMvcConfigurer {

    @Bean
    @LoadBalanced
    public RestTemplate RestTemplate(){
        return new  RestTemplate();
    }
}

conroller

@Autowired
    private RestTemplate  restTemplate;

    public   static  final  String  INVOKE_URL="http://cloud-provider-service";

    @GetMapping("/payment/getZK")
    public String  getdata(){
        String xx=restTemplate.getForObject(INVOKE_URL+"/payment/zk",String.class);
        return  xx;
    }

这里的url直接使用的是http://cloud-provider-service
其中cloud-provider-service是服务端在zookeeper注册的名字。

使用consul

基本使用方法与zookeeper相似
1.去官网下载Linux版本或者windows版本安装
注意安装版本与导入依赖版本

pom

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-consul-discoveryartifactId>
    <version>3.0.0version>
dependency>

yml

server:
  port: 8000

spring:
  application:
    name: cloud-consumer-order

  cloud:
    consul:
      host: local
      port: 8500
      discovery:
        service-name: ${spring.application.name}

剩下的与zookeeper的一致。
spring Cloud项目总结_第5张图片

服务调用

Ribbon

依赖

<dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-ribbonartifactId>
    <version>1.3.5.RELEASEversion>
dependency>

作用是可以修改负载均衡的方式,例如有
随机,轮询等。
在消费者的主启动类上使用

@RibbonClient(value = "cloud-provider-service",configuration = MySelfRule.class)

注解,cloud-provider-service表示需要的服务名。后面的类可以在config上注入到spring boot中,可以在方法中修改负载均衡的匹配方式

@Bean
    public IRule myRule(){
        return  new RandomRule();  //随机
    }

spring Cloud项目总结_第6张图片详细项目在cloud-consumer-order80项目中,
配合使用7001,cloud-provider-payment8001和8001可以查看手写的轮询算法。

OpenFeign

一般在客户端使用,消费者端
详细作用

具体查看 cloud-consumer-openFeign-order80项目,配合7001与基本的8001可以查看效果,相当于是一个接口插件。
使用时需要在主启动类上

@EnableFeignClients 

注解启动openFeign,配合在并在接口上使用

@FeignClient("cloud-provider-service")

后面为需要的服务名。

日志增强功能:

logging:
  level:
   com.atguihu.springcloud.service.paymentOnService: debug   #openFeign的日志增强功能

再在配置类中配置需要的等级

@Configuration
public class FeignConfig {
    @Bean
    public Logger.Level leiel(){
       return Logger.Level.FULL;
    }
}

超时控制功能:

因为openfeign的包包含Ribbon包,所以设置超时
控制即为

ribbon:
  ReadTimeout: 5000   #链接超时时长   超过5秒就报超时
  ConnectTimeout: 5000  #读取超时时长


#  MaxAutoRetries: 0 #同一台服务实例重试次数,不包括首次调用
#  MaxAutoRetriesNextServer: 1 #重试负载均衡其他的服务实例最大重试次数,不包括首次调用
#  OkToRetryOnAllOperations: false # 是否所有操作都重试

超过时间就报错。

服务降级

Hystrix

发生场景,因为微服务之间相互调用,如果其中一个微服务因为(运行问题,超时,宕机)会导致调用者用等待返回值,这样就容易发送雪崩式的服务崩溃。

Hystrix实现了断路器模式,当某个服务发生故障时,通过断路器的监控,给调用方返回一个错误响应,而不是长时间的等待,这样就不会使得调用方由于长时间得不到响应而占用线程,从而防止故障的蔓延。Hystrix具备服务降级、服务熔断、线程隔离、请求缓存、请求合并及服务监控等强大功能。
Hystrix详细教程

Nacos

下载安装: Github安装地址
启动:

windows
直接到bin目录下使用

Linux

暂时启动

startup.cmd -m standalone

yml

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


pom


        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>
   

Sentinel

官方中文文档

安装:点击此处

sentinel的默认端口是8080

pom


        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
        dependency>

        
        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
        dependency>

yml

server:
  port: 8899

spring:
  application:
    name: cloud-sentinel-service

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        service: cloud-sentinel-service

    sentinel:
      transport:
        dashboard: localhost:8080
        port: 8719

主启动

@SpringBootApplication
@EnableDiscoveryClient
public class SentinelMain {
    public static void main(String[] args) {
        SpringApplication.run(SentinelMain.class,args);
    }
}

通过ip加8080,进入sentinel,账户密码均是sentinel

sentinel限流

直接_快速失败(系统默认)
spring Cloud项目总结_第7张图片

当QPS每秒超过10个,sentinel直接返回友好提示
在这里插入图片描述
直接_Warm UP(预热)

spring Cloud项目总结_第8张图片

预热,不会让请求从一个很小的数直接爆发到一个很大的数 ,通过 ,前5秒的阈值是按单机阈值除于3的数,如当前例子,前5秒的阈值为3,经过5秒之后,阈值变成10

直接_排队等待

接收所有QPS,让其一个一个来排队出来,如果新来的预计处理时间大于超时时间,则直接返回友好信息

关联_直接失败
spring Cloud项目总结_第9张图片
当 /lbbb达到阈值时,会导致 /lbba被限流
spring Cloud项目总结_第10张图片

spring Cloud项目总结_第11张图片

你可能感兴趣的:(spring,cloud,spring,cloud)