java学习之springcloud之服务注册与发现篇

参考资料:
尚硅谷springcloud教程

springcloud文档:https://cloud.spring.io/spring-cloud-static/Hoxton.SR1/reference/htmlsingle/
springboot文档:https://docs.spring.io/spring-boot/docs/2.2.2.RELEASE/reference/htmlsingle/

1.springcloud简介与学习版本

springcloud=分布式微服务架构的一站式解决方案,是多重微服务架构落地技术的集合体,俗称微服务全家桶

springcloud所包含的技术
在这里插入图片描述
下面就是我们需要掌握的技术
在这里插入图片描述
下面是学习课程是的版本选型

springboot:2.x版本,springcloud H版
下面这张图是springcloud和springboot版本号的对应

在这里插入图片描述
在这里插入图片描述
最终学习选择的版本:
注意:springcloud版本决定springboot版本,看可以在springcloud官网查看对应版本所推荐的springboot版本,我使用的idea是2022版本的
cloud:
查看springcloud推荐的springboot版本的方式:
在这里插入图片描述
在这里插入图片描述
下面是本次课程中所要学的一些技术(主要是打勾的)
在这里插入图片描述

2.微服务架构编码构建(初体验)

2.1搭建一个微服务整体聚合父工程Project

a)创建一个父maven工程
在这里插入图片描述
修改好字符编码
在这里插入图片描述
b)父工程的pom.xml文件

DependencyManagementDependencies的区别:前者一般用于父工程,使用pom.xml 中的dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号
Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用这个
注意:DependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖(报错的话把他去掉刷新一下maven引入依赖后再加上即可)
只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom
如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。

<?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>com.javalearn.springcloud</groupId>
  <artifactId>springcloudLearn</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>8.0.27</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>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <fork>true</fork>
          <addResources>true</addResources>
        </configuration>
      </plugin>
    </plugins>
  </build>

</project>

2.2支付模块cloud-provider-payment8001

1、建模块
在我们原来的父工程下新建一个模块
在这里插入图片描述
查看父工程的pom,我们发现多出了一个模块
在这里插入图片描述

2、改pom
引入依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>
        <!--mysql-connector-java-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--jdbc-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3、改yml
在resources文件夹中创建一个application.yml文件

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 当前数据源操作类型
    driver-class-name: com.mysql.cj.jdbc.Driver              # mysql驱动包
    url: jdbc:mysql://localhost:3306/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 


mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.javalearn.springcloud.entities    # 所有Entity别名类所在包

4、主启动
即springboot的主启动类,我们在springboot中已经学习过了
在这里插入图片描述

5、业务类

vue->controller->service->dao->mysql

a)建表sql
在这里插入图片描述

b)创建实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Payment implements Serializable {
    private long id;
    private String serial;
}

下面是返回给前端的实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class CommonResult <T>{
    private Integer code;//状态码
    private String message;
    private T data;
    
    public CommonResult(Integer code,String message){
        this(code,message,null);
    }
}

c)dao(Mapper)

@Mapper
public interface PaymentDao {
    public int create(Payment payment);

    public Payment getPaymentById(@Param("id")Long id);
}

同时创建他的映射文件
在这里插入图片描述

<?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.javalearn.springcloud.dao.PaymentDao">
    <!--public int create(Payment payment);-->
    <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id">
        insert into payment (serial) values (#{serial})
    </insert>
    
    <resultMap id="BaseResultMap" type="Payment">
        <id column="id" property="id" jdbcType="BIGINT"/>
        <id column="serial" property="serial" jdbcType="VARCHAR"/>
    </resultMap>
    
    <!--public Payment getPaymentById(@Param("id")Long id);-->
    <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
        select * from payment where id=#{id}
    </select>
</mapper>

d)service

public interface PaymentService {
    public int create(Payment payment);

    public Payment getPaymentById(@Param("id")Long id);
}

以及他的实现类

@Service
public class PaymentServiceImpl implements PaymentService {
    
    @Resource
    PaymentDao paymentDao;

    @Override
    public int create(Payment payment) {
        return paymentDao.create(payment);
    }

    @Override
    public Payment getPaymentById(Long id) {
        return paymentDao.getPaymentById(id);
    }
}

e)controller

@Slf4j
@RestController
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @PostMapping("/payment/create")
    public CommonResult createPayment(Payment payment){
        int result = paymentService.create(payment);
        log.info("****插入结果"+result);

        //返回给前端的数据
        if (result>0){
            return new CommonResult(200,"插入数据苦成功",result);
        }else{
            return new CommonResult(444,"插入数据库失败",null);
        }
    }

    @GetMapping ("/payment/get/{id}")
    public CommonResult getPaymentById(@PathVariable("id") Long id){
        Payment payment = paymentService.getPaymentById(id);

        if (payment!=null){
            return new CommonResult(200,"查询成功",payment);
        }else{
            return new CommonResult(444,"查询失败,查询id:"+id,null);
        }
    }
}

六、测试
经过测试,由于我的idea版本过高,所以用周阳老师的lombok版本会报错,修改了一下版本

    <lombok.version>1.18.20</lombok.version>

在这里插入图片描述
测试查询的时候,由于需要post请求,所以这里使用postman,结果插入成功
在这里插入图片描述
总结:业务模块的步骤
1.建module
2.改pom
3.写yml
4.写run
5.写业务

2.3消费者模块cloud-consumer-order-80(操作支付模块)

1、建模块
在这里插入图片描述
2、改pom

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3、写yml
使用8080端口

server:
  port: 80

4、主启动
在这里插入图片描述

5、写业务

我们使用消费者模块来操作我们刚刚写的支付模块,所以只需要有controller即可

消费者模块也需要用到Payment的实体类,所以我们先复制一份实体类
在这里插入图片描述

2.3.1RestTemplate

接下来写我们的controller类,去调用我们之前写的支付模块,这里就要使用RestTemplate了:是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集

官网https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

使用
使用restTemplate访问restful接口非常的简单粗暴无脑。
(url, requestMap, ResponseBean.class)这三个参数分别代表
REST请求地址、请求参数、HTTP响应转换被转换成的对象类型。

a)配置类,注入RestTemplate

@Configuration
public class ApplicationContextConfig {
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

b)controller

@Slf4j
@RestController
public class OrderController {
    public static final String PAYMENT_URL = "http://localhost:8001";//这个是我们需要转发到的端口
    @Resource
    private RestTemplate restTemplate;
    
    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){
        //调用restTemplate的这个方法
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
    }

    @GetMapping("/consumer/payment/get/{id}")
    public  CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
        return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
    }
}

接下来分别启动80和8001的主启动类,进行测试,启动后idea会弹出一个选项,勾选使用
在这里插入图片描述
这样我们就可以方便的看每一个服务了
在这里插入图片描述
经过测试,我们可以使用consumer模块调用payment模块的查询方法
在这里插入图片描述
但是当我们要调用增加方法时,由于我们的consumer传递给payment模块的是一个json数据,所以我们需要增加一个@RequestBody注解用于接受json字符串,所以要修改8001的代码
在这里插入图片描述

2.4提取两个模块的公共实体类entity

在我们的8001和80两个模块中,他们有重复部分,也就是entities实体类,这就会造成代码的冗余,那么接下来我们就要抽取公共部分了。

还是通过maven抽取,通过新建一个cloud-api-commons模块来抽取

1、建模块(不演示了)

2、改pom

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.0</version>
        </dependency>
    </dependencies>

3、复制前两个工程的实体类
在这里插入图片描述

4、使用maven命令:clean->install

5、删除原来模块中的entities内容,并引入这个自己定义的jar包

        <dependency><!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
            <groupId>com.javalearn.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

到这里,我们的基础构件入门就完成了

3.Eureka服务注册与发现(已停更,了解一下)

3.1基础知识

虽然Eureka目前已经停止更新,但是许多老项目还是在使用的,我们需要先来了解下面的一些概念

1、服务治理

在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册

2、服务注册与发现
Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka的客户端连接到 Eureka Server并维持心跳连接。这样系统的维护人员就可以通过 Eureka Server 来监控系统中各个微服务是否正常运行下图是工作原理。

在这里插入图片描述
其包括两个组件:
Eureka Server提供服务注册服务: 各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
EurekaClient通过注册中心进行访问: 是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)

3.2单机Eureka:cloud-eureka-server7001构建步骤

1、建立一个module:cloud-eureka-server7001

2、改pom

    <dependencies>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.javalearn.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
        <!--boot web actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--一般通用配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <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>

3、写yml

server:
  port: 7001

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

4、创建springboot主启动类
在这里插入图片描述
5、测试
运行主启动类,在浏览器中输入对应网址,进入成功
在这里插入图片描述

3.3支付微服务8001与消费者80入驻进EurekaServer

修改8001模块

1、改pom
注意这里引入的是client,而7001注册中心是sever

        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2、写yml

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

3、主启动
在这里插入图片描述
4、测试
a)注意要先启动7001注册中心

b)如果启动报错
修改一下client依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <!-- 排除Jersey,用SpringMVC Rest方式-->
            <exclusions>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-client</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey.contribs</groupId>
                    <artifactId>jersey-apache-client4</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

c)刷新Eureka界面,发现服务已经注册进来了
在这里插入图片描述
d)发现微服务注册到名称与我们yml文件中的一致
在这里插入图片描述

5、消费者模块80也是一样的流程,直接到测试环节
a)先启动7001,和8001,然后启动80

b)发现80也被注册成功了
在这里插入图片描述

c)到现在为止的工作原理
在这里插入图片描述

3.4搭建Eureka集群

1、集群原理
如果说注册中心只有一台,那么如果他除了故障,整个服务环境就不可用了,所以我们需要搭建集群,下图是到目前为止的工作原理,来保证高可用
集群原理:相互注册,相互守望,并且对外暴露出一个整体,下面是搭建的步骤
在这里插入图片描述
2、建module,参考7001创建cloud-eureka-server7002

3、改pom

   <dependencies>
        <!--eureka-server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
        <dependency>
            <groupId>com.javalearn.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--boot web actuator-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--一般通用配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <!--加上这个防止启动报错-->
        <dependency>
            <groupId>com.thoughtworks.xstream</groupId>
            <artifactId>xstream</artifactId>
            <version>1.4.15</version>
        </dependency>
    </dependencies>

4、修改映射配置
找到C:\Windows\System32\drivers\etc路径下的hosts文件
修改映射配置添加进hosts文件,添加如下内容,方便区分两台sever
在这里插入图片描述

5、写yml
先改7001
在这里插入图片描述

再写7002
在这里插入图片描述

6、创建7002的主启动类,与7001一样,别忘了加注解

7、测试,分别运行7001和7002的主启动类,启动服务
1、经过测试,曾经的localhost还可以访问到Eureka主页

2、访问域名,我们发现1指着2,2指着1,自此集群搭建成功
在这里插入图片描述
在这里插入图片描述

3.5将订单与支付模块注册进Eureka集群

1、注册8001,修改yml
在这里插入图片描述
2、注册80,修改yml
在这里插入图片描述
3、测试
1、启动7001和7002集群,然后启动服务提供者8001,最后启动80

3.6支付微服务提供者8001的集群配置

我们工程目前的架构图是80是消费者,8001是服务的提供者,为了保持高可用,我们微服务的提供者也需要进行集群配置

1、参考8001新建8002

2、改pom
直接复制8001的即可

3、写yml
复制粘贴8001的yml,修改端口为8002即可,此时8001和8002对外暴露的服务名其实是一样的
在这里插入图片描述

4、主启动

5、业务类
也是直接从8001粘贴

6、修改8001和8002的ontroller(重点)
以8001为例,8002也是一样的修改,获取端口号,来获取是哪台服务器执行的请求
在这里插入图片描述
7、测试
启动顺序:7001-7002-8001-8002-80
观察Eureka界面,我们发现支付服务有两台服务器了
在这里插入图片描述
8、修改80的controller

在之前的项目中,我们的80是使用了RestTemplate,所以请求只会转发给8001,达不到集群的效果,所以我们需要修改。

a)在原先的配置类中,使用 @LoadBalanced注解赋予RestTemplate负载均衡能力
在这里插入图片描述
b)修改地址,80controller中的地址,不再写死8001
在这里插入图片描述
这样我们就完成了微服务集群的配置,注意,访问集群的方式默认是轮询,即:你一次我一次

3.7微服务信息完善

目前存在的问题
在这里插入图片描述
a)主机名修改
(1)需要的依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

(2)修改部分
在这里插入图片描述
在这里插入图片描述
b)显示ip
修改部分:在8001和8002的yml中加入
在这里插入图片描述
这样就可以显示ip了

3.8服务发现Discovery

功能:对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息

1、修改8001的controller,8002也是一样的,就不演示了
首先注入DiscoveryClient

    @Resource
    private DiscoveryClient discoveryClient;

然后写一个用于获取信息的方法
通过这个discoveryClient就可以获取微服务信息了

    @GetMapping("/payment/discovery")
    public Object discovery(){
        List<String> services = discoveryClient.getServices();//获取服务列表的信息
        for (String service : services) {
            log.info("****element"+service);
        }

        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");//获取一个微服务名称下面的全部具体实例
        for (ServiceInstance instance : instances) {
            log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
        }

        return discoveryClient;
    }

2、在8001的主启动类上添加注解@EnableDiscoveryClient
在这里插入图片描述

3.9Eureka的自我保护机制与关闭

概念:一句话:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存,属于CAP里面的AP分支,防止了因为网络分区发生故障而去住注销掉一个健康的微服务。
AP:当发生网络分区时,最大努力保证可用性

如果在Eureka Server的首页看到以下这段提示,则说明Eureka进入了保护模式:
在这里插入图片描述
综上,自我保护模式是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何健康的微服务。 使用自我保护模式,可以让Eureka集群更加的健壮、稳定。

那么怎么关闭自我保护机制?

此次演示以7001服务器和8001客户端为例

(1)修改7001的yml文件,关闭自我保护机制
在这里插入图片描述
在运行7001,发现系统提示我们自我保护机制已经关闭了
在这里插入图片描述

(2)修改8001的yml
在这里插入图片描述

4.zookeeper服务注册与发现

在写这篇文章的时候,博主本人之前并未学习过zookeeper,所以这里暂时先跳过,后续学习后回来补。

5.Consul服务注册与发现

官网:https://www.consul.io/intro/index.html
中文文档:https://www.springcloud.cc/spring-cloud-consul.html
安装说明:https://learn.hashicorp.com/consul/getting-started/install.html
下载地址:https://www.consul.io/downloads.html

Consul 是一套开源的分布式服务发现和配置管理系统,由 HashiCorp 公司用 Go 语言开发。
提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格,总之Consul提供了一种完整的服务网格解决方案。

可以干的事情:

文件下载解压后:
在这里插入图片描述
在这个文件夹可以直接用cmd命令运行
在这里插入图片描述
启动以后,在浏览器中输入 http://localhost:8500就可以访问web界面了,还是很漂亮的
在这里插入图片描述

5.1新建支付服务提供者8006注册进consul

1、建module:cloud-providerconsul-payment8006

2、改pom

   <dependencies>
        <!--SpringCloud consul-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3.写yml

###consul服务端口号
server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
  ####consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        service-name: ${spring.application.name}

4、主启动

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

5、业务类controller

@RestController
@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;

    @RequestMapping("/payment/consul")
    public String paymentConsul(){
        return "springcloud with consul: "+serverPort+"\t\t"+ UUID.randomUUID().toString(); 
    }
}

6、测试
运行我们的主启动类,然后去consul的web界面观察
在这里插入图片描述
程序访问也通过
在这里插入图片描述

5.2新建服务消费者80注册进consul

1、新建一个module:cloud-consumerconsul-order80

2、改pom

    <dependencies>
        <!--SpringCloud consul-server -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- SpringBoot整合Web组件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--日常通用jar包配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

3、写yml

###consul服务端口号
server:
  port: 80

spring:
  application:
    name: cloud-consumer-order
####consul注册中心地址
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        #hostname: 127.0.0.1
        #注册进去的名字
        service-name: ${spring.application.name}

4、主启动

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

5、业务类

这里的业务类和我们之前的Eureka下的那个80消费者很相似,也是使用RestTemplate,所以我们拷贝原来的配置类就行
在这里插入图片描述
然后写一个controller

@RestController
@Slf4j
public class OrderConsulController {
    public static final String INVOKE_URL = "http://consul-provider-payment"; //与Eureka类似,我们要转发的服务的注册名字

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping(value = "/consumer/payment/consul")
    public String paymentInfo()
    {
        String result = restTemplate.getForObject(INVOKE_URL+"/payment/consul", String.class);
        System.out.println("消费者调用支付服务(consule)--->result:" + result);
        return result;
    }
}

6、测试
启动顺序:8006->80
在这里插入图片描述
测试访问,发现一切正常
在这里插入图片描述

6.三个注册中心的异同点

1、CAP是什么?
C:Consistency(数据一致性
A:Availability(可用性
P:Partition tolerance(分区容错性

最多只能同时较好的满足两个。
CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求
因此,根据 CAP 原理将 NoSQL 数据库分成了满足 CA 原则、满足 CP 原则和满足 AP 原则三 大类:
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍必的系统,通常性能不是特别高。
在这里插入图片描述

AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
在这里插入图片描述
三种注册中心的对比图

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值