SpringCloud之服务注册中心

一、Eureureka(目前已停用)服务注册与发现

1、Eureureka基础知识

(1)什么是服务治理?
Spring Cloud封装了Netfetflix公司开发的Eureka模块来实现服务治理
在传统的rpc远程调用框架中,管理服务和服务之间的依赖关系比较复杂,管理起来非常麻烦,所以需要使用服务治理,实现服务调用、负载均衡、容错等,实现服务发现与注册。

(2)什么是服务注册与发现?
----服务注册:在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按照服务名分类组织服务清单,服务注册中心还需要以心跳的方式去监控清单中的服务是否可用,若不可用需要从服务清单中剔除,达到排除故障服务的效果。

----服务发现:由于在服务治理框架下运行,服务间的调用不再通过指定具体的实例地址来实现,而是通过向服务名发起请求调用实现。

(3)Eureka的两个组件
----EurekaServer提供服务注册服务
各个服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务列表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。

----EurekaClient通过注册中心访问服务
是一个Java客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳(默认周期为30s),如果EurekaServer在多个心跳周期内没有收到某个节点的心跳,EurekaServer将会从服务列表中把这个服务节点移除(默认90s)。

2、Eureka单机使用
(1)创建一个新的Module,引入eureka-server的pom

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

(2)编写application.yml配置文件

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

(3)编写主配置类,便可以启动服务注册中心,通过http://localhost:7001可以访问服务注册中心

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer //表示该模块为Eureka的服务注册中心
public class EurekaMain7001 {

    public static void main(String[] args) {
        SpringApplication.run(EurekaMain7001.class,args);
    }
}

(4)将其他服务Module添加到服务Eureka注册中心
如何将其他服务注册到服务中心呢?
A、修改pom添加eureka-client依赖

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

B、在application.yml添加如下配置

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

C、在Module主启动类上添加@EnableEurekaClient注解

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class PaymentMain8001 {

    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8001.class,args);
    }
}

D、测试:分别启动cloud-eureka-server7001模块和cloud-provider-payment8001模块
通过http:localhost:7001访问Eureka,可以看到cloud-provider-payment8001模块服务已经注册到EurekaServer中:在这里插入图片描述
Eureka单机整体框图
在这里插入图片描述

3、Eureka集群原理
(1)Eureka集群
如果我们只配置一个Eureka服务端,那么如果这个服务端崩盘,那么所有服务都无法获取,这肯定不是我们不期望的。所以为了保证高可用性,我们需要搭建Eureka集群。
在这里插入图片描述
前面讲原理时已经提到Eureka Server在启动时默认会注册自己,成为一个服务,所以Eureka Server也是一个客户端。也就是说们我们可以配置多个Eureka Server,让他们之间相互注册,当服务提供者向其中一个Eureka注册服务时,这个服务就会被共享到其他Eureka上,这样所有的Eureka都会有相同的服务。

(2)Eureka集群搭建
A、创建一个新的Eureka模块cloud-eureka-server7002,先按照cloud-eureka-server7001对其进行pom,application.yml和启动类的配置

B、修改映射配置
找到C:\Windows\System32\drivers\etc目录下的hosts文件:在这里插入图片描述
在hosts配置文件末尾添加,然后保存关闭:在这里插入图片描述

C、修改cloud-eureka-server7001cloud-eureka-server7002的application.yml实现两者互相注册,相互守望
cloud-eureka-server7001:
在这里插入图片描述
cloud-eureka-server7002:
在这里插入图片描述
D、依次启动7001和7002
可以通过单机版的http://localhost:7001http://localhost:7002访问7001和7002的EurekaServer中心;
也可以通过http://eureka7001.com:7001http://eureka7001.com:7002来访问。
在这里插入图片描述 在这里插入图片描述
通过访问可以同时看到访问7001可以指向7002,访问7002可以指向7001则证明集群搭建成功!

E、将服务注册进Eureka集群:修改application.yml
单机版将服务注册到EurekaServer配置:
在这里插入图片描述
集群版讲服务注册到集群EurekaServer:
在这里插入图片描述
启动80模块和8001模块,访问EurekaServer,可以看到两个服务已经注册到Eureka集群中:
在这里插入图片描述

4、actuator微服务信息完善
Spring Boot Actuator可以帮助你监控和管理Spring Boot应用,比如健康检查、审计、统计和HTTP追踪等。
前提需要在项目pom文件中引入actuator依赖:

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

(1)主机名称(服务名称)的修改
在这里插入图片描述
修改application.yml文件
在这里插入图片描述
修改后等项目重启后进入EurekaServer查看,可以看到显示的名称即为在yml配置文件中指定的eureka.instance.instance-id的值:在这里插入图片描述
(2)访问信息有IP显示
默认不开启的情况下当我们鼠标指向服务名时左下角并不会显示IP,只会显示:http://主机名:port/*
在这里插入图片描述
修改application.yml文件,指定eureka.instance.prefer-ip-address为true
在这里插入图片描述
重启服务后刷新EurekaServer,当鼠标指向服务名称左小角就显示出http://IP:port/*在这里插入图片描述
5、服务发现Discovery

(1)介绍
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
(2)如何使用?
在controller类中依赖注入DiscoveryClient的Bean,然后通过其对象调用其方法实现服务发现。

@RestController
@Slf4j
@RequestMapping("/payment")
public class PaymentController {
    @Resource
    private DiscoveryClient discoveryClient;    //服务发现Discovery
    
    @GetMapping("/discovery")
    public Object discovery(){
        //获取EurekaServer中心注册的服务名
        List<String> services = discoveryClient.getServices();
        for (String service:services){
            log.info("-------------"+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;
    }
}

启动模块调用discovery方法,看控制台打印结果:
在这里插入图片描述
5、Eureka自我保护

(1)概述
保护模式主要用于一组客户端和EurekaServer之间存在网络分区场景下的保护。一旦进入保护模式,EurekaServer将会尝试保护其服务注册表中的数据,也就是不会注销任何微服务

(2)故障现象
如果 在EurekaServer的页面看到下面这段提示,则说明Eureka进入了保护模式:
在这里插入图片描述
(3)导致原因
某时刻一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务 的信息进行保存。属于CAP里面的AP分支。

(4)为神魔Eureka会产生自我保护机制
为了防止EurekaClient可以正常运行,但是与EurekaServer网络不通情况下EurekaServer不会立刻将EurekaClient服务剔除。

(5)什么是自我保护模式
默认情况下,如果EurekaServer在一定的时间内没有收到某个微服务的心跳,EurekaServer将会注销该实例(默认为90s)。当时当网络分区故障发生( 延时、卡顿、拥挤)时,微服务和EurekaServer之间不能够正常通信,以上行为可能变得非常危险,此时本不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式。
在自我保护模式中,EurekaServer会保护服务表中的信息,不在注销任何服务实例。一句话讲解:好死不如赖活着.
(6)如何禁止自我保护模式
A、出厂默认,自我保护机制是开启的:eureka.server.enable-selfpreservation:true
B、关闭自我保护机制
a.Server端
关闭自我保护机制,保证不可用服务被及时剔除:eureka.server.enable-selfpreservation: flase
设置接收心跳间隔时间为2s(默认为90s):eureka.server.eviction-interval-timer-in-ms: 2000
在这里插入图片描述
访问http://eureka7001.com:7001/红色英文提醒显示自我保护机制已关闭。而且后台每隔2s进行一次心跳接收:在这里插入图片描述
b.Client端
#Eureka客户端向服务端发送心跳的时间间隔,单位为s(默认是30s)
eureka.instance.lease-renewal-interval-in-seconds=30
#Eureka服务端在收到最后一次心跳后等待的时间上限,单位为s(默认为90s),超时将剔除服务
eureka.instance.lease-expiration-duration-in-seconds=90

二、SpringCloud整合Zookeeper代替Eureka

1、Zookeeper介绍
zookeeper是一个分布式协调工具,可以实现注册中心的功能

2、进入linux系统使用docker安装zookeeper

docker pull zookeeper

在这里插入图片描述
3、运行zookeepe
查看zookeeper的docker镜像的id

docker images

在这里插入图片描述
官方给出的docker启动命令为:$ docker run --name some-zookeeper --restart always -d zookeeper
此镜像暴露端口:2181(client port:客户端交互) 、2888(follower port:集群)、 3888(election port:选举)

docker run --name zk01 -p 2181:2181 --restart always -d e1763fd3a0e3

在这里插入图片描述
此处我们指定name为zko1,-p选择暴露linux的端口2181映射到docker容器的2181端口,-d指定需要后台运行的zookeeper的id

3、查看启动运行状况

docker ps

在这里插入图片描述
注:有些特殊情况不关闭防火墙可能会导致zookeeper无法访问到
(1)Linux下查看防火墙运行状态:service iptables statussystemctl status firewalld
(2)临时关闭防火墙:service iptables stopsystemctl stop firewalld
(3)永久关闭防火墙:chkconfig iptables offsystemctl disable firewald·
(4)重启防火墙:service iptables restartsystemctl enable firewalld
(5)永久关闭后重启:chkconfig iptables on

4、SpringBoot整合Zookeeper
(1)引入依赖

<!-- SpringBoot整合zookeeper客户端 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>

(2)编写yml配置文件

#服务端口号
server:
  port: 8004
spring:
  application:
    name: cloud-provider-payment8004
  cloud:
    zookeeper:
      connect-string: 安装zookeeper的主机ip:2181

(3)编写主启动类(注意添加@EnableDiscoveryClient注解)

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

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

(4)编写业务实现类

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("/payment/zk")
    public String paymentzk(){
        return "SpringCloud with zookeeper :"+serverPort+"\t"+ UUID.randomUUID().toString();
    }
}

启动主程序将8004服务注册进zookeeper,进入Linux查看docker容器zookeeper容器中是否有payment8004注册服务:
A、然后进入镜像容器中zookeeper的 zkCli.sh,可以查看注册的服务
在这里插入图片描述
在这里插入图片描述
B、查看注册服务的详细信息
在这里插入图片描述
查看到的服务信息为:

{
  "name": "cloud-provider-payment8004",
  "id": "09a096c8-d7e8-46c6-8a5b-12264e743e3a",
  "address": "DESKTOP-2TROCP1",
  "port": 8004,
  "sslPort": null,
  "payload": {
    "@class": "org.springframework.cloud.zookeeper.discovery.ZookeeperInstance",
    "id": "application-1",
    "name": "cloud-provider-payment8004",
    "metadata": {}
  },
  "registrationTimeUTC": 1609904528772,
  "serviceType": "DYNAMIC",
  "uriSpec": {
    "parts": [
      {
        "value": "scheme",
        "variable": true
      },
      {
        "value": "://",
        "variable": false
      },
      {
        "value": "address",
        "variable": true
      },
      {
        "value": ":",
        "variable": false
      },
      {
        "value": "port",
        "variable": true
      }
    ]
  }
}

(5)注册进zookeeper的节点是临时还是持久的呢?
当关闭payment8004服务,查询ls /services/cloud-provider-payment8004,可以发现短时间内是有流水号存在的,但是当超过一次心跳时服务节点被删掉,所以zookeeper的节点是临时的

三、Consul

1、介绍
(1)Consul是一套开源的分布式服务发现和配置管理系统。提供了微服务中的服务治理、配置中心、控制总线等功能。这些功能中的每一个都可以根据需要单独使用,也可以一起使用以构建全方位的服务网站,总之Consul提供了一种完整的服务网格解决方案。
(2)优点:基于raft协议,比较简洁;支持将康检查;同时支持HTTP和DNS协议;支持跨数据中心的WAN集群;提供Web图形页面;跨平台,支持Linux、Mac、Windows。
Consul中文文档

2、Linux系统安装Consul
A、在/home目录下创建consul目录,进入consul,下载安装包:get https://releases.hashicorp.com/consul/1.3.0/consul_1.3.0_linux_amd64.zip
B、解压安装包:unzip consul_1.3.0_linux_amd64.zip
删除安装包:rm- rf consul_1.3.0_linux_amd64.zip
C、安全组配置8300和8500 tcp,防火墙开放8300 8500
D、启动consul:./consul agent -dev -ui -node=consul-dev -client=172.30.71.145 172.30.71.145是服务器的私有ip
E、启动端口8500上的服务器模式的代理,其中ui可以在http:// 机器ip:8500上找到在这里插入图片描述
3、服务提供者注册进Consul
创建子模块:cloud-providerconsul-payment8006
(1)引入依赖

<!--  Springcloud consul-server -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

(2)编写yml

server:
  port: 8006
spring:
  application:
    name: consul-provider-payment8006
  #consul注册中心地址
  cloud:
    consul:
      host: localhost或服务器IP
      port: 8500
      discovery:
        service-name: ${spring.application.name}
      #开启心跳协议
      heartbeat:
        enabled: true 

(3)编写主启动类

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);
    }
}

(4)编写一个简单的业务测试方法

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("/payment/consul")
    public String paymentConsul(){
        return "SpringCloud with consul:"+serverPort+"\t"+ UUID.randomUUID().toString();
    }
}

(5)运行payment8006子模块,前往consol服务中心查看:在这里插入图片描述
可以看到服务已经注册进服务中心。

4、服务消费者注册进Consul
创建子模块:cloud-consumerconsul-order80
(1)引入依赖

<!--  Springcloud consul-server -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

(2)编写yml

server:
  port: 80
spring:
  application:
    name: cloud-consumerconsul-order80
  #consul注册中心地址
  cloud:
    consul:
      host: localhost或服务器IP
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        #开启心跳协议
        heartbeat:
          enabled: true

(3)编写主启动类

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

@SpringBootApplication
@EnableDiscoveryClient  //该注解用于向使用consul或着zookeeper作为注册中心注册服务
public class OrderConsulMain80 {

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

(4)编写一个简单的业务测试方法

package com.atguigu.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();
    }
}
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-payment8006";

    @Resource
    private RestTemplate restTemplate;

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

(5)运行cloud-consumerconsul-order80子模块,测试consul中的服务:
在这里插入图片描述
order80通过consul服务中心调用payment8006中的方法:
在这里插入图片描述
根据返回结果表示能够调用成功。

四、Eureureka、Zookeeper和Consul三种注册服务中心的异同点

(1)

组件名语言CAP服务健康检查对外暴露接口SpringCloud集成
EurekaJavaAP可配支持HTTP已集成
ConsulGoCP支持HTTP/DNS已集成
ZookeeperJavaCP支持客户端已集成

CAP:CAP理论关注粒度是数据而不是整体系统设计
C:Consistency(强一致性)
A:Availability(可用性)
P:Partition Tolerance(分区容错性)
在这里插入图片描述
CAP理论的核心是:一个分布式系统不可能同时满足一致性、可用性和分区容错性这三个需求,最多只能同时较好的满足两个
因此,根据CAP原理将NoSQL数据库分成了满足CA原则、满足CP原则和满足AP原则三大类:
CA-单点集群,满足一致、可用性的系统,通常在扩展性上不太强大。
CP-满足一致性、分区容错性的系统,通常性能不是特别高。
AP-满足可用性、分区容错性的系统,通常可能对一致性要求低一点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值