• 微服务间通信重构与服务治理笔记


    父工程

    依赖版本管理,但实际不引入依赖

    pom.xml

    1. <?xml version="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.0</modelVersion>
    6. <groupId>org.example</groupId>
    7. <artifactId>SpringCloud</artifactId>
    8. <version>1.0-SNAPSHOT</version>
    9. <packaging>pom</packaging>
    10. <!-- 统一管理jar包版本 -->
    11. <properties>
    12. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    13. <maven.compiler.source>1.8</maven.compiler.source>
    14. <maven.compiler.target>1.8</maven.compiler.target>
    15. <junit.version>4.12</junit.version>
    16. <log4j.version>1.2.17</log4j.version>
    17. <lombok.version>1.16.18</lombok.version>
    18. <mysql.version>5.1.47</mysql.version>
    19. <druid.version>1.1.16</druid.version>
    20. <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    21. </properties>
    22. <!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version -->
    23. <dependencyManagement>
    24. <dependencies>
    25. <!--spring boot 2.2.2-->
    26. <dependency>
    27. <groupId>org.springframework.boot</groupId>
    28. <artifactId>spring-boot-dependencies</artifactId>
    29. <version>2.2.2.RELEASE</version>
    30. <type>pom</type>
    31. <scope>import</scope>
    32. </dependency>
    33. <!--spring cloud Hoxton.SR1-->
    34. <dependency>
    35. <groupId>org.springframework.cloud</groupId>
    36. <artifactId>spring-cloud-dependencies</artifactId>
    37. <version>Hoxton.SR1</version>
    38. <type>pom</type>
    39. <scope>import</scope>
    40. </dependency>
    41. <!--spring cloud alibaba 2.1.0.RELEASE-->
    42. <dependency>
    43. <groupId>com.alibaba.cloud</groupId>
    44. <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    45. <version>2.1.0.RELEASE</version>
    46. <type>pom</type>
    47. <scope>import</scope>
    48. </dependency>
    49. <dependency>
    50. <groupId>mysql</groupId>
    51. <artifactId>mysql-connector-java</artifactId>
    52. <version>${mysql.version}</version>
    53. </dependency>
    54. <dependency>
    55. <groupId>com.alibaba</groupId>
    56. <artifactId>druid</artifactId>
    57. <version>${druid.version}</version>
    58. </dependency>
    59. <dependency>
    60. <groupId>org.mybatis.spring.boot</groupId>
    61. <artifactId>mybatis-spring-boot-starter</artifactId>
    62. <version>${mybatis.spring.boot.version}</version>
    63. </dependency>
    64. <dependency>
    65. <groupId>junit</groupId>
    66. <artifactId>junit</artifactId>
    67. <version>${junit.version}</version>
    68. </dependency>
    69. <dependency>
    70. <groupId>log4j</groupId>
    71. <artifactId>log4j</artifactId>
    72. <version>${log4j.version}</version>
    73. </dependency>
    74. <dependency>
    75. <groupId>org.projectlombok</groupId>
    76. <artifactId>lombok</artifactId>
    77. <version>${lombok.version}</version>
    78. <optional>true</optional>
    79. </dependency>
    80. </dependencies>
    81. </dependencyManagement>
    82. <build>
    83. <finalName>cloud</finalName>
    84. <plugins>
    85. <plugin>
    86. <groupId>org.springframework.boot</groupId>
    87. <artifactId>spring-boot-maven-plugin</artifactId>
    88. <version>2.2.2.RELEASE</version> <!-- 与Spring Boot版本对应 -->
    89. <configuration>
    90. <fork>true</fork>
    91. <addResources>true</addResources>
    92. </configuration>
    93. </plugin>
    94. </plugins>
    95. </build>
    96. </project>

    支付模块

    server:
      port: 8081
    
    spring:
      application:
        name: cloud-payment-service
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: org.gjt.mm.mysql.Driver
        url: jdbc:mysql://xxxx:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
        username: xxxx
        password: xxxxxxx
    
    mybatis:
      mapperLocations: classpath:mappers/*.xml
      #这些Java Bean在mapper XML文件中可以使用别名代替全限定类名
      type-aliases-package: com.example.commons.pojo
    logging:
      level:
        com:
          example:
            pay:
              mapper: debug
    
    #将服务注册到Eureka
    eureka:
      client:
        #表示是否将自己注册进EurekaServer默认为true
        register-with-eureka: true
        #是否从EurekaServer抓取已有的注册信息默认true 单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
        fetchRegistry: true
        service-url:
          #defaultZone: http:http://eureka7001.com:7001/eureka/
          #集群版
          defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
    

    模块结构

    依赖     eureka client是后期要用的

      

    
    
        
            SpringCloud
            org.example
            1.0-SNAPSHOT
        
        4.0.0
    
        cloud-provider-payment8081
    
        
            
                org.springframework.cloud
                spring-cloud-starter-netflix-eureka-client
            
            
                org.example
                cloud-api-commons
                ${project.version}
            
            
            
                org.springframework.boot
                spring-boot-starter-web
            
    
            
            
                org.springframework.boot
                spring-boot-starter-actuator
            
    
            
            
                org.mybatis.spring.boot
                mybatis-spring-boot-starter
                2.2.2
            
    
            
            
                com.alibaba
                druid-spring-boot-starter
                1.1.10
            
            
            
                mysql
                mysql-connector-java
            
    
            
            
                org.springframework.boot
                spring-boot-starter-jdbc
            
    
            
            
                org.springframework.boot
                spring-boot-devtools
                runtime
                true
            
    
            
            
                org.projectlombok
                lombok
                true
            
    
            
            
                org.springframework.boot
                spring-boot-starter-test
                test
            
            
            
                org.springframework.boot
                spring-boot-devtools
                runtime
                true
            
        
    
    

    pojo

    映射文件 因后期重构 以移动到commons

     
    
    
        
            insert into payment(serial)value(#{serial})
        
    
        
    

    控制器

    订单模块

    在父工程下创建moudle

    配置RestTemplate

    调用支付模块

    application.yml

    server:
      port: 80
    
    spring:
      application:
        name: cloud-consumer-ord
    #将服务注册到Eureka
    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/
    

    将支付和订单的pojo单独重构放到commons模块并在支付和订单模块分别引入 

    Eureka服务治理

    SpringCloud封装了Netflix公司的Eureka模块来实现服务治理

    Eureka是服务发现与治理的一套解决方案  还有Nacos Zookeeper  Sofa Consul  Etcd  

    在传统的RPC远程调用(如Dubbo,RestTemplate不属于RPC调用)框架中,管理每个服务与服务之间依赖关系比较复杂,所以需要服务治理.实现服务发现与注册.Eureka维护一个服务注册表,其他服务可以查询这个注册表来发现和调用其他微服务.

    Eureka使得各个微服务之间能够相互发现并进行通信,但它本身不提供远程调用的功能

    Eureka采用CS设计架构.Eureka Server做为服务注册功能的服务器.它是服务注册中心,而系统中的其他微服务,使用Eureka的客户端连接到Eureka的Server并通过心跳连接检测.这样系统的维护人员就可以通过Eureka Server来监控系统中各个微服务是否正常运行.

    在服务注册与发现中,有一个注册中心,当服务器启动的时候,会把当前自己服务器的信息,比如服务器通讯地址等以别名方式注册到注册中心.消费者可通过注册中心获取服务通信地址.然后通过RPC调用.任何RPC远程调用框架都会有一个注册中心(存放服务地址相关信息包括接口地址)

    Eureka包含两个组件:Eureka Server和Eureka Client

    Eureka Server提供服务注册

    各个微服务节点通过配置启动之后,会在EurekaServer进行注册,这样EurekaServer中的服务注册表中将存储可用服务的节点信息.

    Eureka Client通过注册中心访问

    是一个Java客户端,为了简化EurekaServer的交互,客户端同时也具备一个内置的,使用轮询(round-robin)负载算法的负载均衡器.应用启动后,将会向Eureka Server发送心跳(默认30秒发送一次).如果Eureka Server在多个心跳周期内没有接收到某个节点发送的心跳.EurekaServer将会从服务注册表中将该节点移除(默认90秒)

    单机版Eureka服务注册中心构建

    @EnableEurekaServer表示我是一个EurekaServer

    application.yml

    server:
      port: 7001
    
    eureka:
      instance:
        hostname: localhost  # eureka服务端的实例名称
      client:
        # 表示不向注册中心注册自己
        register-with-eureka: false
        # 表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址  ${}是上面定义的
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

    pom.xml

    1. <?xml version="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. <parent>
    6. <artifactId>SpringCloud</artifactId>
    7. <groupId>org.example</groupId>
    8. <version>1.0-SNAPSHOT</version>
    9. </parent>
    10. <modelVersion>4.0.0</modelVersion>
    11. <artifactId>cloud-eureka-server-7001</artifactId>
    12. <properties>
    13. <maven.compiler.source>8</maven.compiler.source>
    14. <maven.compiler.target>8</maven.compiler.target>
    15. </properties>
    16. <dependencies>
    17. <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
    18. <dependency>
    19. <groupId>org.springframework.cloud</groupId>
    20. <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    21. </dependency>
    22. <dependency>
    23. <groupId>org.example</groupId>
    24. <artifactId>cloud-api-commons</artifactId>
    25. <version>${project.version}</version>
    26. </dependency>
    27. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
    28. <dependency>
    29. <groupId>org.springframework.boot</groupId>
    30. <artifactId>spring-boot-starter-web</artifactId>
    31. </dependency>
    32. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
    33. <dependency>
    34. <groupId>org.springframework.boot</groupId>
    35. <artifactId>spring-boot-starter-actuator</artifactId>
    36. </dependency>
    37. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
    38. <dependency>
    39. <groupId>org.springframework.boot</groupId>
    40. <artifactId>spring-boot-devtools</artifactId>
    41. <scope>runtime</scope>
    42. <optional>true</optional>
    43. </dependency>
    44. <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
    45. <dependency>
    46. <groupId>org.projectlombok</groupId>
    47. <artifactId>lombok</artifactId>
    48. </dependency>
    49. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
    50. <dependency>
    51. <groupId>org.springframework.boot</groupId>
    52. <artifactId>spring-boot-starter-test</artifactId>
    53. <scope>test</scope>
    54. </dependency>
    55. <dependency>
    56. <groupId>junit</groupId>
    57. <artifactId>junit</artifactId>
    58. </dependency>
    59. </dependencies>
    60. </project>

    localhost:7001/

    支付模块完成服务注册

    首先引入依赖

    
        org.springframework.cloud
        spring-cloud-starter-netflix-eureka-client
    

    启动类加上客户端注解

    application.yml

    #将服务注册到Eureka
    eureka:
      client:
        #表示是否将自己注册进EurekaServer默认为true
        register-with-eureka: true
        #是否从EurekaServer抓取已有的注册信息默认true 单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
        fetchRegistry: true
        service-url:
          defaultZone: http://localhost:7001/eureka
    

    订单模块完成服务注册

    依赖

    
        org.springframework.cloud
        spring-cloud-starter-netflix-eureka-client
    

    访问 localhost:7001/

    Eureka服务治理集群构建

    目的高可用,如果单个Eureka服务挂了,会导致整个服务环境不可用

    搭建Eureka注册中心集群,实现负载均衡+故障容错

    比如有两台Eureka服务 7001和7002

    那就是相互注册  

    如果是三台 7001  7002  7003  

    那么就是7001注册 7002和7003         7002注册7001和7003     7003注册7001和7002

    两两相望  相互注册

    为了看的清除

    C:\Windows\System32\drivers\etc\hosts

    127.0.0.1  eureka7001.com
    127.0.0.1  eureka7002.com

    pom.xml

    
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-server
        
    
        
            org.example
            cloud-api-commons
            ${project.version}
        
    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
    
        
        
            org.springframework.boot
            spring-boot-starter-actuator
        
    
        
        
            org.springframework.boot
            spring-boot-devtools
            runtime
            true
        
    
        
        
            org.projectlombok
            lombok
        
    
        
        
            org.springframework.boot
            spring-boot-starter-test
            test
        
        
            junit
            junit
        
    
    

     主启动类

    application.yml配置文件需要相互注册

    server:
      port: 7002
    
    
    eureka:
      instance:
        hostname: eureka7002.com  # eureka服务端的实例名称
      client:
        # 表示不向注册中心注册自己
        register-with-eureka: false
        # 表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
        fetch-registry: false
        service-url:
          # 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址  ${}是上面定义的
          #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
          defaultZone: http://eureka7001.com:7001/eureka/

    在原先7001的application里修改配置

    互相启动

    支付模块和订单模块注册到服务治理集群

    修改订单服务的application.yml

    修改支付服务的application.yml

    支付模块微服务集群搭建

    剩下就是个复制过程

    注意 对外暴露都是同一个服务名  重要

    那么现在就牵扯出另外一件事   到底调用哪个服务   和  负载均衡

    完成后

    现在调用

    那么订单这边也不能写死了

    使用服务名

    使用Ribbon做负载均衡

    @LoadBalanced注解 表示使用Ribbon进行负载均衡

    该注解是引入Eureka客户端依赖时引入的  默认轮询

    默认是轮询策略  可以修改配置

    Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号,且该服务还有负载功能.

    其实就是引入了Eureka客户端依赖 就可以使用@LoadBalanced注解 是Ribbon的功能

    actuator微服务信息完成功能

    一般来说 web和actuator最好一起导入

    原先的

    在支付和订单模块

    看下修改后的效果

    那么原先的显示怎么回事

    看下host

    localhost:8081/actuator/health

    让Eureka界面上有IP显示

    服务发现Discovery

    就是说Eureka上面很多服务,那么这些服务对应的信息比如 IP什么什么的

    可以通过服务发现Discovery来获取该服务的信息

    我单在8081里使用

    发现不写这个注解也可以   上面没写

    Eureka的自我保护

    下面这排红字

    概述:保护模式主要用于一组客户端和Eureka Server之间存在网络分区场景下的保护,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务

    上面红字就是说Eureka进入了保护模式

    在保护模式下,某时刻一个微服务即使不可用,Eureka也不会立即清理,依旧会对该微服务的信息进行保存,属于CAP理论的AP分支

    为什么会产生Eureka自我保护机制

    为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通情况下,防止错误剔除

    什么是自我保护模式:

    默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳,EurekaServer将会注销实例(默认90秒).但是当网络分区故障发生(延时,卡顿,拥挤)时,微服务与EurekaServer之间无法正常通信,以上行为可能变得非常危险---因为微服务本身其实是健康的,此时不应该注销这个服务.Eureka通过自我保护模式来解决这个问题。当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式.

    禁止自我保护,宁可杀错,不可放过,配置绝情版Eureka(我乱说的)

    Eureka停更说明(嘿嘿)

    github.com/Netflix/eureka/wiki

  • 相关阅读:
    R语言绘制高密度散点图
    Spring Cloud网关路由谓词
    JavaEE 初始spring
    一体化污水处理设备在使用中有哪些故障?该如何解决?
    SpringBoot整合Mybatis-Plus(含自动配置分析)
    Ubuntu或Mac (M1) 上安装Pymol
    大数据开发面试笔记Day1
    php 实现:给图片加文字水印,图片水印,压缩图片
    设计模式七大原则-单一职责原则SingleResponsibility
    如何使用vsCode打开intel D435i深度相机
  • 原文地址:https://blog.csdn.net/tiantiantbtb/article/details/136399885