Spring cloud入门-7:服务注册中心-Consul单机环境构建

1、consul简介

1.1 what is consul

  Consul uses service identities and traditional networking practices to help organizations securely connect applications running in any environment.
在这里插入图片描述

1.2 Common use cases for Consul

1、Discover Services with Consul:服务发现,提供http和dns两种发现方式。
2、Health Monitoring with Consul:实时的健康检查
3、Observability with Consul:可视化界面
在这里插入图片描述

2、安装consul

首先是下载linux版的consul:https://www.consul.io/downloads
在这里插入图片描述
我的系统是Ubuntu16.04,按照官网命令安装即可。
安装完成后,查看是否安装成功:consul --version

koping@koping-HP:~$ consul --version
Consul v1.11.1
Revision 2c56447e
Protocol 2 spoken by default, understands 2 to 3 (agent will automatically use protocol >2 when speaking to compatible agents)

接下来使用开发模式启动:。数据是存储在内存中,重启之后数据将丢失

consul agent -dev
koping@koping-HP:~$ consul agent -dev
==> Starting Consul agent...
           Version: '1.11.1'
           Node ID: '9b6e4720-3b08-49a1-427e-a81fe2aa0634'
         Node name: 'koping-HP'
        Datacenter: 'dc1' (Segment: '<all>')
            Server: true (Bootstrap: false)
       Client Addr: [127.0.0.1] (HTTP: 8500, HTTPS: -1, gRPC: 8502, DNS: 8600)
      Cluster Addr: 127.0.0.1 (LAN: 8301, WAN: 8302)
           Encrypt: Gossip: false, TLS-Outgoing: false, TLS-Incoming: false, Auto-Encrypt-TLS: false

==> Log data will now stream in as it occurs:

2022-01-13T12:18:16.880+0800 [INFO]  agent.server.raft: initial configuration: index=1 servers="[{Suffrage:Voter ID:9b6e4720-3b08-49a1-427e-a81fe2aa0634 Address:127.0.0.1:8300}]"
2022-01-13T12:18:16.880+0800 [INFO]  agent.server.raft: entering follower state: follower="Node at 127.0.0.1:8300 [Follower]" leader=
2022-01-13T12:18:16.880+0800 [INFO]  agent.server.serf.wan: serf: EventMemberJoin: koping-HP.dc1 127.0.0.1
2022-01-13T12:18:16.881+0800 [INFO]  agent.server.serf.lan: serf: EventMemberJoin: koping-HP 127.0.0.1
2022-01-13T12:18:16.881+0800 [INFO]  agent.router: Initializing LAN area manager
2022-01-13T12:18:16.881+0800 [INFO]  agent.server: Adding LAN server: server="koping-HP (Addr: tcp/127.0.0.1:8300) (DC: dc1)"
2022-01-13T12:18:16.881+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=udp
2022-01-13T12:18:16.881+0800 [INFO]  agent.server: Handled event for server in area: event=member-join server=koping-HP.dc1 area=wan
2022-01-13T12:18:16.881+0800 [WARN]  agent: grpc: addrConn.createTransport failed to connect to {dc1-127.0.0.1:8300 0 koping-HP <nil>}. Err :connection error: desc = "transport: Error while dialing dial tcp 127.0.0.1:0->127.0.0.1:8300: operation was canceled". Reconnecting...
2022-01-13T12:18:16.881+0800 [INFO]  agent: Started DNS server: address=127.0.0.1:8600 network=tcp
2022-01-13T12:18:16.881+0800 [INFO]  agent: Starting server: address=127.0.0.1:8500 network=tcp protocol=http
2022-01-13T12:18:16.881+0800 [WARN]  agent: DEPRECATED Backwards compatibility with pre-1.9 metrics enabled. These metrics will be removed in a future version of Consul. Set `telemetry { disable_compat_1.9 = true }` to disable them.
2022-01-13T12:18:16.881+0800 [INFO]  agent: started state syncer
2022-01-13T12:18:16.881+0800 [INFO]  agent: Consul agent running!
2022-01-13T12:18:16.881+0800 [INFO]  agent: Started gRPC server: address=127.0.0.1:8502 network=tcp
2022-01-13T12:18:16.941+0800 [WARN]  agent.server.raft: heartbeat timeout reached, starting election: last-leader=
2022-01-13T12:18:16.941+0800 [INFO]  agent.server.raft: entering candidate state: node="Node at 127.0.0.1:8300 [Candidate]" term=2
2022-01-13T12:18:16.941+0800 [DEBUG] agent.server.raft: votes: needed=1
2022-01-13T12:18:16.941+0800 [DEBUG] agent.server.raft: vote granted: from=9b6e4720-3b08-49a1-427e-a81fe2aa0634 term=2 tally=1
2022-01-13T12:18:16.941+0800 [INFO]  agent.server.raft: election won: tally=1
2022-01-13T12:18:16.941+0800 [INFO]  agent.server.raft: entering leader state: leader="Node at 127.0.0.1:8300 [Leader]"
2022-01-13T12:18:16.942+0800 [INFO]  agent.server: cluster leadership acquired
2022-01-13T12:18:16.942+0800 [INFO]  agent.server: New leader elected: payload=koping-HP
2022-01-13T12:18:16.946+0800 [INFO]  agent.leader: started routine: routine="federation state anti-entropy"
2022-01-13T12:18:16.946+0800 [INFO]  agent.leader: started routine: routine="federation state pruning"
2022-01-13T12:18:16.946+0800 [DEBUG] agent.server.autopilot: autopilot is now running
2022-01-13T12:18:16.946+0800 [DEBUG] agent.server.autopilot: state update routine is now running
2022-01-13T12:18:16.947+0800 [DEBUG] connect.ca.consul: consul CA provider configured: id=fb:50:9b:45:1a:65:15:c1:68:57:73:5f:da:cd:b8:0d:0f:e2:26:eb:68:66:43:11:85:9d:67:a9:7a:56:9c:b9 is_primary=true
2022-01-13T12:18:16.949+0800 [INFO]  connect.ca: initialized primary datacenter CA with provider: provider=consul
2022-01-13T12:18:16.949+0800 [INFO]  agent.leader: started routine: routine="intermediate cert renew watch"
2022-01-13T12:18:16.949+0800 [INFO]  agent.leader: started routine: routine="CA root pruning"
2022-01-13T12:18:16.949+0800 [INFO]  agent.leader: started routine: routine="CA root expiration metric"
2022-01-13T12:18:16.949+0800 [INFO]  agent.leader: started routine: routine="CA signing expiration metric"
2022-01-13T12:18:16.949+0800 [INFO]  agent.leader: started routine: routine="virtual IP version check"
2022-01-13T12:18:16.949+0800 [DEBUG] agent.server: successfully established leadership: duration=7.187553ms
2022-01-13T12:18:16.949+0800 [INFO]  agent.server: member joined, marking health alive: member=koping-HP partition=default
2022-01-13T12:18:16.949+0800 [DEBUG] agent.leader: stopping routine: routine="virtual IP version check"
2022-01-13T12:18:16.949+0800 [DEBUG] agent.leader: stopped routine: routine="virtual IP version check"
2022-01-13T12:18:16.964+0800 [INFO]  agent.server: federation state anti-entropy synced
2022-01-13T12:18:17.138+0800 [DEBUG] agent: Skipping remote check since it is managed automatically: check=serfHealth
2022-01-13T12:18:17.139+0800 [INFO]  agent: Synced node info
2022-01-13T12:18:17.139+0800 [DEBUG] agent: Node info in sync
2022-01-13T12:18:18.014+0800 [DEBUG] agent: Skipping remote check since it is managed automatically: check=serfHealth
2022-01-13T12:18:18.014+0800 [DEBUG] agent: Node info in sync

显示Consul agent running!后,再访问consul的前端界面,端口号是默认的8500:http://localhost:8500/
在这里插入图片描述

3、构建服务提供模块

和之前eureka、zookeeper一样,现在需要构建服务提供者模块注册进consul中。

3.1、建module

在cloud2021父工程下,构建cloud-provider-payment-consul-8006模块:
在这里插入图片描述

3.2、改pom

  依赖文件参考上一节博文的zookeeper的依赖包,只是将spring-cloud-starter-zookeeper-discovery给替换为了:spring-cloud-starter-consul-discovery。

<?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>cloud2021</artifactId>
        <groupId>org.example.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-provider-payment-consul-8006</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- 导入 zookeeper客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- 导入公共包-->
        <dependency>
            <groupId>org.example.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- spring boot web 依赖模块: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-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
            <version>1.14.0</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

3.3、写yml

配置文件与之前也一致,需要填写服务端口号,服务注册中心IP地址,端口号,注册服务名称等:

server.port=8006

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

3.4、主启动

在主启动类上面还是要添加@SpringBootApplication和@EnableDiscoveryClient这2个注解。
在这里插入图片描述

package com.example.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

3.5、业务类

业务类与上一节的zookeeper一致,只是返回consul的端口信息+一个随机UUID字符串:
在这里插入图片描述

package com.example.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

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

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

3.6、测试

启动服务提供模块的主启动类:PaymentMain8006。
启动成功后,刷新consul的监控主页面,可以看到服务提供模块已经成功注册进入consul中:
在这里插入图片描述
然后,通过postman调用服务接口,可以得到consul端口号和一个随机的uuid字符串结果:
在这里插入图片描述

4、构建服务消费模块

4.1、建module

在cloud2021父工程下新建服务消费模块:cloud-consumer-order-consul-80
在这里插入图片描述

4.2、写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">
    <parent>
        <artifactId>cloud2021</artifactId>
        <groupId>org.example.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud-consumer-order-consul-80</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- 导入 zookeeper客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>
        <!-- 导入公共包-->
        <dependency>
            <groupId>org.example.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- spring boot web 依赖模块: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-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

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

4.3、改yml

server.port=8080

# 服务别名--注册到consul的服务名称
spring.application.name=cloud-consumer-order
# consul服务注册中心地址
spring.cloud.consul.host=localhost
spring.cloud.consul.port=8500
spring.cloud.consul.discovery.hostname=127.0.0.1
spring.cloud.consul.discovery.service-name=${spring.application.name}

4.4、主启动

在这里插入图片描述

package com.example.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

4.5、业务类

首先还是要配置restTemplate远程调用bean,然后调用服务提供模块得到结果:

在这里插入图片描述
在这里插入图片描述

package com.example.springcloud.config;

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

@Configuration
public class ApplicationContextConfig {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}
package com.example.springcloud.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@Slf4j
public class OrderConsulController {
    public static final String INVOKE_URL = "http://consul-provider-payment";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping(value = "/consumer/payment/consul")
    public String paymentInfo() {
        String result = restTemplate.getForObject(INVOKE_URL + "/payment/consul", String.class);
        return result;
    }
}

4.6、测试

启动消费服务模块,查看consul注册中心,发现已成功注册消费服务模块:
cloud-consumer-order。
在这里插入图片描述
其次,通过消费服务模块8080端口调用服务提供者的8006的接口,发现可以获取到服务提供者返回的数据:
在这里插入图片描述

5、三个注册中心的异同点

5.1、测试consul服务宕机

  在前几篇博文中,介绍了当服务宕机后,eureka会在一段时候(默认90s)之后才会移除服务,并且具有自我保护机制。而zookeeper在规定心跳时间后未收到心跳,则直接移除了。那么consul是哪种情况?
  接下来,将服务提供者停掉进行测试。如下图,当服务提供者宕机后,provider服务几秒后就被移除。
  在这里插入图片描述

5.2、CAP定理

  经过测试可以发现,当服务不可用时,eureka很在一段时间后,才会将服务移除。而zookeeper和consul则是在心跳周期内未收到心跳就会很快移除服务。
  接下来引出CAP定理:CAP定理指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可同时获得
  在这里插入图片描述

  • 一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(所有节点在同一时间的数据完全一致,节点越多,数据同步越耗时)
  • 可用性(A):负载过大后,集群整体是否还能响应客户端的读写请求。(服务一直可用,而且是正常响应时间)
  • 分区容错性(P):分区容忍性,一个节点崩了,并不影响其它的节点(100个节点,挂了几个,不影响服务,机器越多越好)

  CAP定理提出三者不可同时获得的原因如下:

  • C A 满足的情况下,P不能满足的原因
    数据同步(C)需要时间,还要在正常的时间内响应(A),那么机器数量就要少,所以P就不满足
  • C P 满足的情况下,A不能满足的原因
    数据同步(C)需要时间,机器数量也多§,但是同步数据需要时间,所以不能在正常时间内响应,所以A就不满足
  • A P 满足的情况下,C不能满足的原因
    机器数量多§,正常的时间内响应(A),那么数据就不能及时同步到其他节点,所以C不满足

  在分布式系统中(机器数量多),由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。所以我们只能在一致性和可用性之间进行权衡
  因此之前博文中介绍的Eureka注册中心就属于AP,即服务明明已经不可用了,但Eureka并没有移除,而是继续返回数据,保证了服务的可用性,但是降低了数据的一致性。
  而Zookeeper,Consul则属于CP,即心跳周期内检测到服务不可用了,就立刻移除服务。保证了数据一致性,但是服务可用性降低了。
  Eureka,Zookeeper,Consul三者的异同点如下:
  在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值