SpringCloud_H(服务注册和发现)

1、父类编写pom依赖控制版本

<?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.atguigu</groupId>
    <artifactId>springcloud</artifactId>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>cloud-provider-payment8001</module>
    </modules>
    <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>
        <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、provider-payment-8001 (提供者)

  • maven依赖
    <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.20</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>
  • controller
@RestController
@Slf4j
public class PaymentController {

    @Autowired
    private PaymentService paymentService;

    //向数据局插入数据
    @PostMapping("/payment/create")
    public CommonResult create(Payment payment){
        
        int result = paymentService.create(payment);
        log.info("插入的结果:" + result);

        
        if (result > 0){
            //如果成功插入,返回状态码 200 
            return new CommonResult(200,"插入数据库成功",result);
        }else {
            return new CommonResult(444,"插入数据库失败",result);
        }
    }

    //从数据库查询数据
    @GetMapping("/payment/getPaymentById/{id}")
    public CommonResult getPaymentById(@PathVariable("id") long id){
        Payment payment = paymentService.getPaymentById(id);

        if (payment != null){
            log.info("查询的结果:"+ payment.toString());
            return new CommonResult(200,"查找成功",payment);
        }else {
            return new CommonResult(444,"查找失败");
        }
    }
}

3、consumer-80 (消费者)

  • maven依赖
    <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>
  • application.yml
server:
  port: 80
  • RestTemplate:
    • RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问restful服务模板类,是spring提供的用于访问Rest服务的客户端模板工具类,使用consumer-80到provider-8001的远程调用
  • 编写RestTeplate配置文件
package com.atguigu.springcloud.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ApplicationContextConfig {

    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  • controller 调用provider服务的接口
package com.atguigu.springcloud.controller;

import com.atguigu.springcloud.entity.CommonResult;
import com.atguigu.springcloud.entity.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@Slf4j
public class OrderController {

    //提供者provider的url地址
    public static final String PAYMENT_URL = "http://localhost:8001";

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/create")
    public CommonResult<Payment> create(Payment payment){

        /***
         * 参数1: 请求地址
         * 参数2: 请求参数
         * 参数3: 响应转换的对象类型
         */
        return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
    }

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

4、工程重构

  • 项目中存在相同的代码(如entity包下面的实体类),造成代码冗余,可以进行重构

  • 创建工程 cloud-api-commons

  • maven依赖

    <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>
  • 将privider 和 consumer 中的实体类文件entity 拷贝到当前项目中
  • 使用maven打包发布到本地仓库(install)
  • 删除provider 和 consumer 中的entity,引入cloud-api-commons
        <dependency>
            <groupId>com.atguigu</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

5、Eureka服务注册和发现

5.1、Eureka基础知识

  • 服务治理

    • springcloud 封装了Netflix公司开发的Eureka模块来实现服务治理
    • 在传统的rpc远程调用框架中,管理每个服务与微服务之间依赖关系比较复杂,管理比较复杂,所有需要使用服务治理,管理服务于服务之间的依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
  • 服务注册

    • Eureka采用了CS的设计架构,Eureka Server 作为服务注册功能的服务器,它是服务注册中心,而系统中的其他微服务,使用Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员可以通过Eureka Server来监控系统中各个微服务是否正常运行
    • 在服务注册与发现中,有一个注册中心。当服务器启动的时候,会把当前自己服务器信息(如服务地址通信地址等)以别名的方式注册到注册中心。另一方(消费者服务提供者),以该别名的方式注册中心上获取实际的通信地址,然后再实现本地RPC调用RPC远程调用框架核心设计思想:在于注册中心,因为使用注册中心管理每个服务与服务之间的一种依赖关系(服务治理概念)。在任何rpc远程调用,都会有一个注册中心(存放服务地址相关信息(接口地址))

image.png

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

5.2、单机Eureka构建步骤

  • 创建 cloud-eureka-server7001服务
  • maven依赖
    <dependencies>
        <!--eureka server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <!--引入自己定义的api通用包-->
        <dependency>
            <groupId>com.atguigu</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>
    </dependencies>
  • application.yml
server:
  port: 7001
eureka:
  instance:
    hostname: localhost # eureka服务端的实例名称
  client:
    register-with-eureka: false # false 表示不向注册中心注册自己
    fetch-registry: false # false 是否从Eureka Server 抓取已有的注册信息
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  • 在启动类上添加 EnableEurekaServer 注解,服务端

  • localhost:7001访问Eureka Server

image.png

  • 将provider-8001注册到Eureka Server

  • 添加Eureka Client依赖

        <!--eureka-client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
  • 在application.yml添加Eureka Client配置信息
eureka:
  client:
    register-with-eureka: true  # ture 自己注册到 Eureka Server
    fetch-registry: true  # 是否从Eureka Server 抓取已有的注册信息
    service-url:
      defaultZone: http://localhost:7001/eureka
  • 在启动类上添加 @EnableEurekaClient 注解,客户端

  • 访问Eureka Server

image.png

  • 使用同样的步骤将comsumer-80服务注册到Eureka Server

image.png

5.3、Eureka集群

  • 在C:\Windows\System32\drivers\etc下hosts文件中添加地址映射
127.0.0.1       eureka7001.com
127.0.0.1       eureka7002.com
  • 修改 eureka7001、eureka7002的配置文件,让两个Eureka Server相互注册
  • eureka7001
server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com # eureka服务端的实例名称
  client:
    register-with-eureka: false # false 表示不向注册中心注册自己
    fetch-registry: false # false 表示自己就是注册中心
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka  # 注册到 EurekaServer 7002
  • eureka7002
server:
  port: 7002
eureka:
  instance:
    hostname:  eureka7002.com # eureka服务端的实例名称
  client:
    register-with-eureka: false # false 表示不向注册中心注册自己
    fetch-registry: false # false 表示自己就是注册中心
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka  # 注册到 EurekaServer 7001
  • 访问 7001Eureka服务

image.png

  • 访问 7002Eureka服务

image.png

  • 修改provider-8001 和 consumer-80 两个服务的配置文件,将两个服务分别注册到Eureka7001,和Eureka7002
eureka:
  client:
    register-with-eureka: true  # ture 自己注册到 Eureka Server
    fetch-registry: true  # 是否从Eureka Server 抓取已有的注册信息
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka

image.png


image.png

5.4、provider集群配置

  • 新建项目 cloud-provider-payment8002

  • provider8002和provider8001除了端口号不同其他一样的配置

image.png

  • 在consuemr80的配置类RestTemplate对象上添加 @LoadBalanced 注解,赋予RestTemplate负载均衡能力
@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced  //使用@LoadBalanced注解赋予RestTemplate负载均衡能力
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  • 将consumer80服务controller中提供者的url地址改为提供者的服务名称
    //提供者provider的url地址
    //public static final String PAYMENT_URL = "http://localhost:8001";
    public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";

5.5、actuator微服务信息完善

  • 修改服务名称
  • 访问信息有ip显示
eureka:
  client:
    register-with-eureka: true  # ture 自己注册到 Eureka Server
    fetch-registry: true  # 是否从Eureka Server 抓取已有的注册信息
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  instance:
    instance-id: privider8001  # 修改服务名称
    prefer-ip-address: true # 访问信息ip地址

image.png

5.6、服务发现Discovery

  • 对于注册进Eureka里面的微服务,可以通过服务发现来获得该服务的信息
  • 修改provider8001的Controller
@RestController
@Slf4j
public class PaymentController {

    //服务发现
    @Autowired
    private EurekaDiscoveryClient discoveryClient;

    
    //获取Eureka中的服务信息
    @GetMapping("/payment/discovery")
    public Object discovery(){

        //Eureka中的 Application
		List<String> services = discoveryClient.getServices();
        for (String element:services){
            log.info("======>"+element);
        }

        //指定Application下的具体信息
        List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        for (ServiceInstance instance:instances){
            log.info(instance.getServiceId()+" "+instance.getHost()+" "+instance.getPort()+" "+ instance.getUri());
        }

        return this.discoveryClient;
    }
}
  • 在启动类添加 @EnableDiscoveryClient 注解,开启Euerka服务发现功能
@SpringBootApplication
@EnableEurekaClient //Eureka Client
@EnableDiscoveryClient  //开启 Eureka 服务发现功能
public class PaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class,args);
    }
}
  • 控制台输出
# Eureka中的 Application
======>cloud-payment-service
======>cloud-order-service

# CLOUD-PAYMENT-SERVICE 的具体信息
CLOUD-PAYMENT-SERVICE 172.25.152.61 8002 http://172.25.152.61:8002
CLOUD-PAYMENT-SERVICE 172.25.152.61 8001 http://172.25.152.61:8001

5.7、Eureka自我保护

  • 保护模式主要用于客户端和Eureka Server之间存在网络分区场景下的保护,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务
  • 某时刻某一微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存

image.png

  • 禁止自我保护

  • Eureka Server 7001

server:
  port: 7001
eureka:
  instance:
    hostname: eureka7001.com # eureka服务端的实例名称
  client:
    register-with-eureka: false # false 表示不向注册中心注册自己
    fetch-registry: false # false 表示自己就是注册中心
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
      # defaultZone: http://eureka7002.com:7002/eureka  # 注册到 EurekaServer 7002
  server:
    enable-self-preservation: false # 关闭自我保护机制
    eviction-interval-timer-in-ms: 2000  # 清理无效服务的时间间隔
  • Eureka Client 8001
eureka:
  client:
    register-with-eureka: true  # ture 自己注册到 Eureka Server
    fetch-registry: true  # 是否从Eureka Server 抓取已有的注册信息
    service-url:
      # defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
      defaultZone: http://eureka7001.com:7001/eureka
  instance:
    instance-id: privider8001  # 修改服务名称
    prefer-ip-address: true # 访问信息ip地址
    lease-renewal-interval-in-seconds: 1 # Eureka客户端向服务端发送心跳的时间间隔 默认30s
    lease-expiration-duration-in-seconds: 2 # Eureka服务端在收到最后一次心跳后等待时间上限,默认90s,超时将剔除服务

6、Zookeeper服务注册和发现

6.1、docker安装zookeeper

  • 拉取镜像
docker pull zookeeper:3.4.9
  • 运行zookeeper
docker run -d -p 2181:2181 zookeeper:3.4.9
  • 进入zookeeper客户端
docker exec -it 3465b21f6fa6 zkCli.sh

6.2、provider-8004服务注册到zookeeper

  • 新建项目 cloud-provider-payment8004
  • maven依赖
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <!--排除start中包含的zookeeper-->
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <!--使用和服务器安装的zookeeper一样的版本-->
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </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>
  • application.yml配置文件
server:
  port: 8004

spring:
  application:
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: 82.156.13.249:2181  # zookeeper服务IP地址和端口号
  • 启动类 添加 @EnableDiscoveryClient 服务发现注解
@SpringBootApplication
@EnableDiscoveryClient  //服务发现
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class,args);
    }
}
  • controller
@RestController
@Log4j
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/zk")
    public String paymentZK(){
        return "springCloud with zookeeper:"+serverPort;
    }
}
  • 启动provider-8004服务

  • 在zookeeper中查看服务信息

image.png

6.3、consumer-81注册到zookeeper

  • maven依赖和provider-8004一样
  • application.yml
server:
  port: 81

spring:
  application:
    name: cloud-consumer-order
  cloud:
    zookeeper:
      connect-string: 82.156.13.249:2181  # zookeeper服务IP地址和端口号
  • 配置类,注入RestTemplate
@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced  //使用@LoadBalanced注解赋予RestTemplate负载均衡能力
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  • 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class OrderMain81 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain81.class,args);
    }
}
  • controller,调用provider-8004服务
@RestController
public class OrderZKController {

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

    @Autowired
    private RestTemplate restTemplate;


    @GetMapping("/consumer/payment/zk")
    public String paymentInfo(){
        String res = restTemplate.getForObject(INVOKE_URL+"/payment/zk",String.class);
        return res;
    }
}
  • 启动consumer81
[zk: localhost:2181(CONNECTED) 20] ls /services
[cloud-provider-payment, cloud-consumer-order]
  • 同过conmer-81调用provider-8004获取数据

image.png

7、Consul服务注册和发现

7.1、Consul简介

  • Consul是一套开源的分布式服务发现和配置管理系统,由HashiCorp公司用Go语言开发
  • 提供了微服务系统中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网格。
  • 它具有很多优点,包括:基于raft协议,比较简洁;支持健康检查,同时支持HTTP和DNS协议 支持跨数据中心的 WAN 集群 提供图形界面 跨平台,支持linux mac windows

7.2、docker安装consul

  • 拉取镜像
docker pull consul:1.6.1
  • 运行consul
docker run -d -p 8500:8500 consul:1.6.1
  • 访问consul图形界面

image.png

7.3、provider-8006服务注册到consul

  • maven依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

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

        <dependency>
            <groupId>com.atguigu</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </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>
  • application.yml
server:
  port: 8006

spring:
  application:
    name: consul-provider-payment
  cloud:
    consul:
      host: 82.156.13.249
      port: 8500
      discovery:
        hostname: 82.156.13.249
        service-name: ${spring.application.name}
        heartbeat:
          enabled: true
        prefer-ip-address: true
  • 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class PaymentMain8006 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8006.class,args);
    }
}
  • controller
@RestController
@Slf4j
public class PaymentController {
    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/consul")
    public String paymentConsul(){
        return "spring cloud with consul" + serverPort;
    }
}
  • 访问consul图形化界面

image.png

7.4、consumer-83服务注册到consul

  • maven依赖和provider-8006一样
  • application.yml
server:
  port: 83
spring:
  application:
    name: cloud-consumer-order

  cloud:
    consul:
      host: 82.156.13.249
      port: 8500
      discovery:
        hostname: 82.156.13.249
        service-name: ${spring.application.name}
        heartbeat:
          enabled: true
        prefer-ip-address: true
  • 启动类
@SpringBootApplication
@EnableDiscoveryClient
public class OrderMain83 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain83.class,args);
    }
}
  • 配置类,注入RestTemplate
@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced  //使用@LoadBalanced注解赋予RestTemplate负载均衡能力
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}
  • controller
@RestController
public class OrderConsulController {

    private String INVOKE_URL = "http://consul-provider-payment";
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/consumer/payment/consul")
    public String payment(){
        String res = restTemplate.getForObject(INVOKE_URL + "/payment/consul", String.class);
        return res;
    }
}
  • 启动consumer-83服务

image.png

  • 通过consumer-83服务调用provider8006服务

image.png

8、三个注册中心异同点

组件名 语言 CAP 服务健康检查 对外暴露接口 Spring Cloud集成
Eureka Java AP 可配支持 HTTP 已集成
Consul Go CP 支持 HTTP DNS
Zookeeper Java CP 支持 客户端 已集成
  • CPA理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求
    • CA-单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大
    • CP-满足一致性,分区容错性的系统,通常新能不是特别高
    • AP-满足可用性,分区容错性的系统,通常对一致性要求低一些
posted @ 2022-11-06 22:40  youmo~  阅读(30)  评论(0编辑  收藏  举报