SpringCloud框架(一) -- 服务注册与发现Eureka(弃)、zookeeper及consul(弃)

先来个:Eureka、Consul、Zookeeper的异同点:

在这里插入图片描述
Eureka(AP):保证可用性。比如保证预售阶段点赞、喜欢、想要等的可用性,具体点赞、喜欢、想要的人数有多少,他不关心。

Zookeeper及Consul(CP):保证数据的一致性,比如确保数据是正确的,加入你服务器挂了也并不关心。

CAP:

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

1. Eureka

1.1 基础知识:

1.1.1 服务治理:

Spring Cloud 封装了Netflix公司开发的Eureka模块来实现服务治理

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

1.1.2 服务注册与发现

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

1.1.3 Eureka的两个组件:Eureka Server和Eureka Client

在这里插入图片描述

1.2. 单机Eureka

1.2.1 创建Eureka7001项目:

在这里插入图片描述

1.2.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.angenin.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    <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>
1.2.3 编写yml文件:
server:
  port: 7001

eureka:
  instance:
    hostname: localhost  #eureka服务端的实例名称
  client:
    #false表示不向注册中心注册自己(想注册也可以,不过没必要)
    register-with-eureka: false
    #false表示自己端就是注册中心,职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false
    service-url:
      #设置与eurekaServer交互的地址查询服务和注册服务都需要依赖这个地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
1.2.4 Euraka服务主启动

在主启动类上添加@EnableEurekaServer //表示此项目是eureka的服务注册中心,启动后访问http://localhost:7001/

在这里插入图片描述

1.2.5 将生产者消费者注册进euraka:

将payment8001和order8010注册进Eureka成为服务提供方:

  1. 在需要注册的项目pom文件中添加jar包,注意此处和server端不一样,是clinet
<!--eureka client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  1. 在yml中添加Eureka相关配置
eureka:
  client:
    #表示是否将自己注册进EurekaServer默认为true,不注册就是false
    register-with-eureka: true
    #是否从EurekaServer抓取已有的注册消息,默认为true,单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url:
      #集群版
      #defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
      #单机版
      defaultZone: http://eureka7001.com:7001/eureka/
  1. 在启动类上添加注解@EnableEurekaClient,表示此项目是euraka客户端,并启动:

在这里插入图片描述

  1. 其中我们在yml中设置的spring.application.name就是我们注册进eureka中的服务名

1.3. 集群Eureka

在这里插入图片描述

1.3.1 单服务注册会导致的问题: 在这里插入图片描述
1.3.2 Eureka集群的关键:互相注册,相互守望

在这里插入图片描述

1.3.3 搭建Eureka7002:
  1. 重复上述7001步骤
  2. 修改yml文件,设置为7001和7002互相注册
eureka:
  instance:
  	#eureka服务端的实例名称,这么写需要去修改hosts文件
    hostname: eureka7002.com 
  client:
    # false表示不向注册中心注册自己
    register-with-eureka: false
    # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要检索服务
    fetch-registry: false
    service-url:
      # 设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
      # 单机
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
      # 相互注册,7002中注册7001,7001中注册7002
      #defaultZone: http://eureka7002.com:7002/eureka/
      defaultZone: http://eureka7001.com:7001/eureka/
  1. 启动后可以看到,7001中注册了7002,7002中注册了7001
    在这里插入图片描述
1.3.4 服务注册进集群eureka
  1. 将payment8001和order注册进集群,修改yml文件中eureka中service-url配置:
service-url:
   #集群版
   defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
   #单机版
   #defaultZone: http://localhost:7001/eureka/
  1. 启动后查看并调用:
    在这里插入图片描述
1.3.5 搭建服务提供方payment集群环境
  1. 新建payment8002项目,和8001一样配置,不多说
  2. 在项目Controller中放入自己的端口号,测试被调用的服务是哪个,业务代码不多说
@Value("${server.port}")
private String serverPort;

在这里插入图片描述

1.3.6 负载均衡
  1. 修改order中的调用,之前是写死的调用8001,现在改为调用在Eureka上对外暴露的微服务名称即:
application: # 注册进服务的名称
	name: cloud-payment-service
// public static final String PAYMENT_URL = "http://localhost:8001";
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
  1. 然后在消费者的ApplicationContextConfig里的restTemplate方法上加上@LoadBalanced,开启负载均衡功能
@Bean
@LoadBalanced //赋予RestTemplate负载均衡的能力
public RestTemplate getRestTemplate() {
    return  new RestTemplate();
}
  1. 启动项目后可以看到,调用payment服务时是按照轮询的方式调用8001和8002

1.4. actuator微服务信息完善:

存在的问题:

  1. 服务名称不规范
  2. 我们并不能知道这个服务在哪个服务器上即哪个ip,希望当我们把鼠标放在服务名上时,可以知道这个服务是哪台服务器上的
1.4.1 完善Eureka中注册的ip名称,设置访问路径可以显示ip地址:

修改yml文件,在eurela配置中添加:

  # 跟client平级
  instance:
    instance-id: payment8001 # 设置服务名称
    prefer-ip-address: true #访问路径可以显示ip

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

1.5 服务发现:

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

实现方式:

  1. 修改8001的Controller:
@Resource
private DiscoveryClient discoveryClient;


@GetMapping(value = "/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  this.discoveryClient;
}
  1. 在启动类上添加@EnableDiscoveryClient注解
  2. 调用方法:
    在这里插入图片描述

1.6 Eureka的自我保护:

1.6.1 什么是eureka自我保护机制

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

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

1.6.2 如何关闭自我保护模式

即:只要掉线了,立马删掉服务

  1. 在7001的yml中添加配置
  server:
    #关闭自我保护模式,保证不可用服务被及时删除
    enable-self-preservation: false
    #心跳的间隔时间,单位毫秒
    eviction-interval-timer-in-ms: 2000
  1. 在8001的yml的instance中配置
instance:
    instance-id: payment8001
    prefer-ip-address: true #访问路径可以显示ip
    #Eureka客户端向服务端发送心跳的实际间隔,单位为秒(默认为30秒)
    lease-renewal-interval-in-seconds: 1
    #Eureka服务端收到最后一次心跳后等待时间上线,单位为秒(默认为90秒) 超时将剔除服务
    lease-expiration-duration-in-seconds: 2

在这里插入图片描述

2. zookeeper

2.1 注册中心Zookeeper

在这里插入图片描述
zookeeper也是有心跳机制,在一定时间能如果一直没心跳返回,Zookeeper就会把服务节点剔除掉。所以在Zookeeper上的服务节点是临时节点

2.2 zookeeper的启动:
  1. 关闭防火墙
systemctl stop firewalld
systemctl status firewalld
  1. docker启动Zookeeper
#拉取Zookeeper镜像
docker pull zookeeper

#启动Zookeeper
docker run --name zk01 -p 2181:2181 --restart always -d zookeeper
2.3 服务提供者注册进zookeeper
  1. 新建工程cloud-provider-payment8004
  2. pom文件:
<!--因为接下来不会用到数据库,所以不导入数据库相关的依赖(防止没配置而报错)-->

	<!--替换掉eureka依赖,其他直接复制8001-->
        <!--SpringBoot整合Zookeeper客户端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!--        <exclusions>-->
            <!--先排除自带的zookeeper3.5.3-->
<!--            <exclusion>-->
<!--                <groupId>org.apache.zookeeper</groupId>-->
<!--                <artifactId>zookeeper</artifactId>-->
<!--            </exclusion>-->
<!--        </exclusions>-->
        </dependency>

        <!--添加zookeeper3.4.9版本(引入对应版本的依赖)-->
<!--        <dependency>-->
<!--            <groupId>org.apache.zookeeper</groupId>-->
<!--            <artifactId>zookeeper</artifactId>-->
<!--            <version>3.4.9</version>-->
<!--        </dependency>-->
  1. 编写yml文件
#端口号
server:
  port: 8004

spring:
  application:
    #服务别名——注册到zookeeper注册中心的名称
    name: cloud-provider-payment
  cloud:
    zookeeper:
      connect-string: ip:2181 #linux的ip加暴露的端口号
  1. 主启动类添加注解:
@EnableDiscoveryClient	//该注解用于向使用consul或者Zookeeper作为注册中心时注册服务
@SpringBootApplication
public class PaymentMain8004 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8004.class, args);
    }
}
  1. 新建controller测试:
@Slf4j
@RestController
public class PaymentController {

    @Value("${server.port}")        //获取端口号
    private String serverPort;

    @RequestMapping("/payment/zk")
    public String paymentzk(){
        return "springcloud with zookeeper:" + serverPort + "\t" + UUID.randomUUID().toString();
    }
}
  1. 启动服务并调用接口:
    在这里插入图片描述

  2. 进入zookeeper容器内部查看:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.4 服务消费者注册进zookeeper
  1. 新建消费者模块cloud-consumerzk-order80。

  2. pom和yml直接复制8004。(yml中端口号改为80,应用名改为cloud-consumer-order,其他都相同)

  3. 主启动类。(与8004相同)

  4. 在springcloud包下新建config.ApplicationContextConfig

@Configuration
public class ApplicationContextConfig {

    @Bean
    @LoadBalanced   //负载均衡
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}
  1. 新建controller.OrderZKController
@RestController
@Slf4j
public class OrderZKController {

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

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/payment/zk")
    public String paymentInfo(){
        String result = restTemplate.getForObject(INVOKE_URL + "/payment/zk", String.class);
        return result;
    }
}
  1. 启动项目
    在这里插入图片描述
    在这里插入图片描述

3. consul

Consul官网:https://www.consul.io/
Consul中文文档:https://www.springcloud.cc/spring-cloud-consul.html

3.1 简介

Consul是一种服务网格解决方案,提供具有服务发现,配置和分段功能的全功能控制平面。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建完整的服务网格。Consul需要一个数据平面,并支持代理和本机集成模型。Consul附带了一个简单的内置代理,因此一切都可以直接使用,还支持Envoy等第三方代理集成
在这里插入图片描述

3.2 主要特点

  • 服务发现:Consul的客户端可以注册服务,例如 api或mysql,其他客户端可以使用Consul来发现给定服务的提供者。使用DNS或HTTP,应用程序可以轻松找到它们依赖的服务。

  • 健康检测:领事客户端可以提供任意数量的运行状况检查,这些检查可以与给定服务(“ Web服务器是否返回200 OK”)或本地节点(“内存利用率低于90%”)相关。操作员可以使用此信息来监视群集的运行状况,服务发现组件可以使用此信息将流量从不正常的主机发送出去。

  • KV存储:应用程序可以将Consul的分层键/值存储用于多种目的,包括动态配置,功能标记,协调,领导者选举等。简单的HTTP API使其易于使用。

  • 安全的服务通信:领事可以为服务生成并分发TLS证书,以建立相互TLS连接。 意图 可用于定义允许哪些服务进行通信。可以使用可以实时更改的意图轻松管理服务分段,而不必使用复杂的网络拓扑和静态防火墙规则。

  • 多数据中心:Consul开箱即用地支持多个数据中心。这意味着Consul的用户不必担心会构建其他抽象层以扩展到多个区域。

Consul旨在对DevOps社区和应用程序开发人员友好,使其非常适合现代,灵活的基础架构

3.3 docker启动

#拉取consul镜像
docker pull consul

#启动consul
docker run -d  -p 8500:8500/tcp --name myConsul  consul agent -server -ui -bootstrap-expect=1 -client=0.0.0.0

浏览器访问:http://ip/:8500
在这里插入图片描述

3.4 服务提供者注册进consul

  1. 新建服务提供者cloud-provider-consul-payment8006。
  2. pom复制8004。(用下面的依赖替换Zookeeper的依赖)
<!--SpringCloud consul-server-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
  1. 修改yml文件
server:
  port: 8006


spring:
  application:
    name: consul-provider-payment
  cloud:
    consul:
      host: 10.211.55.17  #用linux的ip地址(consul在本机就填localhost)
      port: 8500
      discovery:
        service-name: ${spring.application.name}
  1. 主启动类(与8004相同)
  2. controller
@RestController
@Slf4j
public class PaymentController {

    @Value("${server.port}")        //获取端口号
    private String serverPort;

    @RequestMapping("/payment/consul")
    public String paymentConsul(){
        return "springcloud with zookeeper:" + serverPort + "\t" + UUID.randomUUID().toString();
    }
}
  1. 启动项目:
    在这里插入图片描述

  2. 访问接口:
    在这里插入图片描述

3.5 服务消费者注册进consul

  1. 新建模块cloud-consumer-consul-order80
  2. pom(与8006相同)
  3. yml(端口号为80,应用名为consul-consumer-order,其他和8006相同)
  4. 主启动类(与8006相同)
  5. config(和zk的消费者相同)
  6. controller.OrderConsulController
@RestController
@Slf4j
public class OrderConsulController {

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

    @Resource
    private RestTemplate restTemplate;

    @RequestMapping("/consumer/payment/consul")
    public String paymentInfo(){
        String result = restTemplate.getForObject(INVOKE_URL + "/payment/consul", String.class);
        return result;
    }
}
  1. 启动项目
    在这里插入图片描述

  2. 测试
    在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值