菜鸟的springcloud学习总结(二):服务注册中心
说明
更新时间:2020/9/29 15:02,更新到了Consul
更新时间:2020/9/28 00:13,更新到了Eureka
本文主要对springcloud进行学习与记录,本文会持续更新,不断地扩充
本文仅为记录学习轨迹,如有侵权,联系删除。
一、服务注册中心
服务注册中心
管理各种服务功能包括服务的注册、发现、熔断、负载、降级等,比如dubbo admin后台的各种功能。
为何要使用服务注册中心
在第一篇文章(菜鸟的springcloud学习总结(一):前言)中已经实现了服务的调用,但那个是没有用到springcloud任何组件件的,服务之间调用的方式也是简单的,具体如下
如果是多个服务,二三十个服务的情况下,他们的调用关系将是一个复杂的网格,如下
当有更多的服务的情况下就更复杂了,所以这个时候就需要用的服务注册中心,这样的话服务之间的调用方式就变成了这样
这种方式方便管理,而且可以监控各个服务之间的状态
二、Eureka
Eureka作为一个服务注册中心组件,主要分为Eureka Server和Eureka Client,一个服务端,负责提供服务注册服务,注册后,就可以看到所有可用的服务;另一个是客户端,负责向注册中心进行访问;总的来说就是Eureka Server 作为服务注册功能的服务器,它是服务注册中心。而系统中的其他微服务,使用 Eureka 的客户端连接到 Eureka Server,并维持心跳连接。
这张图就简单介绍了整个Eureka的基本架构
Eureka Server | 提供服务注册和发现 |
Service Provider | 服务提供方,将自身服务注册到Eureka,从而使服务消费方能够找到 |
Service Consumer | 服务消费方,从Eureka获取注册服务列表,从而能够消费服务 |
(1)单节点Eureka
Eureka服务端
首先需要自己创建一个Eureka服务模块(cloud-eureka-7001),创建的方式跟之前子模块的创建方式一样,然后修改pom文件,引入eureka的服务端依赖,下面给出个人用到的该模块的所有依赖
<?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>spring_cloud01</artifactId>
<groupId>com.zsc</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-eureka-server7001</artifactId>
<dependencies>
<!--引入公共包-->
<dependency>
<groupId>com.zsc</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!-- eureka-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--springboot starter启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</dependencies>
</project>
将该项目改为springboot项目,并且在主启动类上加上Eureka服务端注解
配置yml配置文件
server:
port: 7001
spring:
application:
name: cloud-eureka-server7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
注册完启动该项目,访问http://localhost:7001/
Eureka客户端
在原来的支付模块( cloud-provider-payment8001)引入pom坐标依赖
<!--eureka client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
配置yml文件
server:
port: 8001
spring:
application:
name: cloud-provider-payment8001
eureka:
client:
#将自己注册进eureka服务中心
register-with-eureka: true
fetch-registry: true
#对应的eureka服务端的地址
service-url:
defaultZone: http://localhost:7001/eureka
主启动类上加上Eureka客户端注解
分别启动Eureka服务端(cloud-eureka-7001)和Eureka客户端(cloud-provider-payment8001),再访问http://localhost:7001/
同理,可以将上次的消费者模块也加入Eureka服务注册中心
(2)Eureka集群
像上面的单节点Eureka容易出现单点故障问题,即一个配置的Eureka出现
掉,这个时候就需要用到Eureka集群
像上面这张图,里面的Eureka Server是有多个的,也就是集群,下面就开始搭建集群
实战
前面单机的时候 eureka注册中心实例名称 是localhost,现在是集群,不能三个实例都是localhost,这里复杂的办法是搞三个虚拟机,麻烦,这里有简单办法,直接配置本机hosts,来实现本机域名映射;因为这是在一台win10系统的电脑上模拟集群搭建,所以需要修改host文件,如图
创建多个Eureka模块,这里在单节点的基础上又创建了两个Eureka服务端模块,组成3个节点的集群,如图
修改7001项目的yml文件,修改的方式也简单,只需要将其他两个节点的地址通过defaultZone配置进来即可,即相互注册即可
server:
port: 7001
spring:
application:
name: cloud-eureka-server7001
eureka:
instance:
#eureka服务端的实例名称
hostname: eureka7001.com
# hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,
fetch-registry: false
service-url:
#搭建eureka集群,需要相互注册其他的eureka服务端,这里开了3个节点,7001,7002,7003
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
接下来是7002项目的yml文件
server:
port: 7002
spring:
application:
name: cloud-eureka-server7002
eureka:
instance:
#eureka服务端的实例名称
hostname: eureka7002.com
# hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,
fetch-registry: false
service-url:
#搭建eureka集群,需要相互注册其他的eureka服务端,这里开了3个节点,7001,7002,7003
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
最后是7003项目的yml文件
server:
port: 7003
spring:
application:
name: cloud-eureka-server7003
eureka:
instance:
#eureka服务端的实例名称
hostname: eureka7003.com
# hostname: localhost #eureka服务端的实例名称
client:
#false表示不向注册中心注册自己
register-with-eureka: false
#false表示自己端就是注册中心,
fetch-registry: false
service-url:
#搭建eureka集群,需要相互注册其他的eureka服务端,这里开了3个节点,7001,7002,7003
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
这样,3个节点的集群就搭建完成了,启动上面3个项目
最后对支付模块和消费者模块的yml进行修改,入住到各个Eureka节点的服务注册中心当中,下面给出支付模块的注册方式,其余模块也是类型的
eureka:
client:
#将自己注册进eureka服务中心
register-with-eureka: true
fetch-registry: true
#对应的eureka服务端的地址
service-url:
#集群的情况下,服务的入住
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7002.com:7002/eureka/
(3)服务集群
前面实现了Eureka集群,但是自己看eureka官网给出的这张图,里面还有一个Service Provider集群
Service Provider就是服务提供者,上面项目的里面的支付模块就是一个服务提供者,消费者调用支付模块,服务提供者也可以搭建集群,实现高可用
这里以支付模块为例,搭建一个支付模块集群,先创建一个支付模块cloud-provider-payment8002,内容跟cloud-provider-payment8001一样
同时集群访问,有一个负载均衡的调配,所以为了区分出8001和8002两个服务,可以在接口那里做一个标记,这里用端口号做标记,到时候就可以直接看到调的是哪一个服务
同时需要修改一个这两个项目的一些东西
这样集群的搭建基本完成,接下来是消费者(cloud-consumer-order80)调用这边,需要配置负载均衡,修改消费者模块的配置类
消费者模块调用订单服务
开启对应的项目
访问eureka
访问消费者,通过消费者调用支付服务
(4)actuator微服务信息完善
现在服务中心已经有服务入住,这个时候可以修改一个这些服务的的名称
需要引入下面对应的坐标
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--springboot starter启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
这是个spiringboot项目,引入actuator的springboot坐标即可,此时可以通过配置文件修改服务名称
以8001支付模块为例,可以看到8001是修改过的,8002是未修改的
(5)服务发现
当我们把服务入住到服务注册中心后,我们可以获取里面的所有服务模块的信息,当服务注册中心入住了服务1,服务2,那么在服务注册中心里面的任一服务模块,可以获取这个服务注册中心的所有每一个服务的信息,下面给出例子
启动了两个服务,支付服务模块和消费者服务模块,在消费者服务模块的控制器暴露一个接口,用来获取服务中心的每一个服务的信息
/**
* 服务发现,对外暴露该服务的相关信息
*/
@Resource
private DiscoveryClient discoveryClient;
@GetMapping("/discovery")
public Object discovery(){
//获得服务中心的所有服务
List<String> services = discoveryClient.getServices();
services.forEach(s->{
System.out.println("==========================================================");
System.out.println("服务名称 = " + s);
//根据服务名称获取到服务的实例
List<ServiceInstance> instances = discoveryClient.getInstances(s);
instances.forEach(instance->{
//服务的主机
System.out.println("服务的主机【instance.getHost()】 = " + instance.getHost());
//注册的服务id
System.out.println("注册的服务id【instance.getServiceId()】 = " + instance.getServiceId());
//服务的端口号
System.out.println("服务的端口号【instance.getPort()】 = " + instance.getPort());
//服务的uri
System.out.println("服务的uri【instance.getUri()】 = " + instance.getUri());
});
});
return this.discoveryClient;
}
然后重新启动消费者服务模块,访问接口http://localhost/consumer/discovery,查看控制台输出
可以看到服务注册中心的两个服务的所有信息。
(6)Eureka自我保护机制
简单讲就是:当某一个时刻,注册中心里面的某一个服务不可用了,Eureka不会立刻删除该服务,而是保留一段时间,下面给出例子
首先是服务端,关闭自我保护机制,并且设置清除无效节点的时间为2s
客户端
这样的话,只有服务一出现问题就直接被移除
三、Consul
简单介绍一下Consul,Consul是一个服务网格(微服务间的 TCP/IP,负责服务之间的网络调用、限流、熔断和监控)解决方案,它是一个一个分布式的,高度可用的系统,而且开发使用都很简便。它提供了一个功能齐全的控制平面,主要特点是:服务发现、健康检查、键值存储、安全服务通信、多数据中心。
下面主要用Consul配合docker使用Consul服务的注册与发现功能,效果就跟上面的Eureka一样。
Eureka和Consul的区别
简单说一下这两个的区别,Eureka采用的c/s架构,它的服务端需要我们自己引入jar包后进行开发,就是创建个springboot项目,引入jar包后,进行简单的配置即可,所以在学习eureka的时候,我们不用下载任何东西,秩序引入jar包即可再配置一下即可;而Consul就不一样,它需要先下载Consul,再把服务注册到Consul里面。
安装Consul
这里采用docker的方式进行安装,安装命令
docker pull consul
创建consul文件对数据进行挂载
运行容器
docker run -d --restart=always -p 8500:8500 -v $PWD/consul:/consul/data -e CONSUL_BIND_INTERFACE='eth0' --name=consul01 consul agent -server -bootstrap -ui -client='0.0.0.0'
成功后即可访问http://ip:8500/就可以访问到页面
服务的开发
在原来的项目上创建一个新的模块cloud-provider-consul-payment8006,引入坐标,重点是SpringCloud Consul的坐标,同时这是一个springboot项目
<dependencies>
<!--引入公共包-->
<dependency>
<groupId>com.zsc</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<!--springboot starter启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--单元测试-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--SpringCloud consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
创建配置文件yml
server:
port: 8006
spring:
application:
name: consul-provider-payment
cloud:
consul:
host: 139.26.222.74
port: 8500
discovery:
#对外暴露的服务名称
service-name: ${spring.application.name}
#维持心跳
heartbeat:
enabled: true
基本配置完成,接下来可以写接口了,为例方便测试,这里就随便写了一个接口
注意在启动类加上一个注解@EnableDiscoveryClient
运行后可以查看Consul页面,就可以查看入住的服务了
这里可以在配置一下消费者模块cloud-consumer-consul-order80,调用上面入住的支付服务,一样的引入坐标,坐标跟上面的基本一样,重点还是Consul的坐标
<!--SpringCloud consul-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
创建配置类,就跟之前写的消费者模块一样
然后是接口,这里还没有用springcloud对应的组件,而是使用restTemplate进行服务的调用
注意在启动类加上一个注解@EnableDiscoveryClient
完成后运行照样可以调用,而且consul页面也显示有两个模块入住