父工程
依赖版本管理,但实际不引入依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.example</groupId>
    <artifactId>SpringCloud</artifactId>
    <version>1.0-SNAPSHOT</version>
   
    <packaging>pom</packaging>
    <!-- 统一管理jar包版本 -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>4.12</junit.version>
        <log4j.version>1.2.17</log4j.version>
        <lombok.version>1.16.18</lombok.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
    </properties>
    <!-- 子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version  -->
    <dependencyManagement>
        <dependencies>
            <!--spring boot 2.2.2-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud Hoxton.SR1-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--spring cloud alibaba 2.1.0.RELEASE-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.spring.boot.version}</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
                <optional>true</optional>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <build>
        <finalName>cloud</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.2.2.RELEASE</version> <!-- 与Spring Boot版本对应 -->
                <configuration>
                    <fork>true</fork>
                    <addResources>true</addResources>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
 
 
支付模块
模块结构
依赖 eureka client是后期要用的
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringCloud</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-provider-payment8081</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
    </dependencies>
</project> 
pojo


映射文件 因后期重构 以移动到commons
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.pay.mapper.PaymentMapper">
    <insert id="createPayment" useGeneratedKeys="true" keyProperty="id">
        insert into payment(serial)value(#{serial})
    </insert>
    <select id="getPaymentById" resultType="com.example.commons.pojo.payment">
        select * from payment where id=#{id}
    </select>
</mapper> 
控制器

订单模块
在父工程下创建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

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SpringCloud</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud-eureka-server-7001</artifactId>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web  -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
    </dependencies>
</project>
 
 
localhost:7001/
支付模块完成服务注册
首先引入依赖
启动类加上客户端注解

application.yml

订单模块完成服务注册
依赖


访问 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



主启动类

application.yml配置文件需要相互注册
在原先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












