文章目录
SpringCloud请看: https://blog.csdn.net/qq_52681418/article/details/113247805
微服务-服务注册中心
CAP原理: C、A、P无法共存,两两组合。
- C :一致性,集群之中多个节点数据一致。违反时有时候会拿到旧数据。
- A :可用性,所有节点都高可用,且无延迟。违反时有时服务无法访问。
- P :分区容忍,可以分区存储数据,节点之间可以通信。
BASE理论:此理论是CAP原理的折中,即最终一致、基本可用、软状态。满足AP的注册中心也可满足此理论。
- 服务调用者:需要调用微服务的服务。
- 服务提供者:被调用的微服务。
- 注册中心:提供者在此注册服务、调用者在此发现服务。
服务提供者将自己的信息注册到注册中心,服务调用者从注册中心取到微服务的信息(如通过服务名获取ip+端口),通过取到的信息对服务进行调用。
通过这种方式,微服务ip、端口变化时,注册中心将提供最新的服务信息提供给调用者。
几个重要概念:
- 服务注册:将服务信息注册到注册中心,其它服务可以通过注册中心调用。
- 服务发现:调用者通过注册中心发现服务。
- 服务调用:调用者通过注册中心获取服务信息,并调用服务。
- 服务高可用:服务保证可用,不会因为宕机而无法提供服务。
- 注册中心集群:注册中心也是服务,因此搭建多个注册中心,注册中心可以注册到其它注册中心,保证注册中心的高可用。
Nacos(AP)
这里只以nacos作为注册中心来介绍。
Nacos是阿里巴巴的微服务组件,可用直接使用在SpringCloud项目中,内部集成了Ribbon。
Nacos提供了服务注册与发现、服务配置中心、以及可视化服务管理平台。
1.搭建Nacos服务
nacos服务已经被官方打包好,你只需要下载并启动就行:
1.下载nacos并解压
- nacos server下载:https://github.com/alibaba/nacos/releases
2.可以直接单机启动:在nacos\bin目录下执行命令(1.4.1版本)。
# windows下的启动,standalone代表着单机模式运行,非集群模式 startup.cmd -m standalone #启动并挂后台,不加&时关闭控制台窗口后,服务关闭 startup.cmd -m standalone & #windows下的停止 shutdown.cmd
上面的操作将使用默认的内嵌式数据库,本次主要作为注册中心,不需要持久化,所以使用默认的就行了。
此时可以直接访问管理界面:http://127.0.0.1:8848/nacos/,账号名/密码为 nacos/nacos。
2.服务注册与发现
注意:无论是消费者还是生产者,都是nacos的客户端,因此都需要进行nacos配置,如果消费者不进行配置,就无法消费直接消费nacos上的服务。
手动进行服务注册、服务发现:
Nacos的服务注册、发现,实际上都是接口,一般是自动,当然也可以手动模拟。
注册接口POST:http://127.0.0.1:8848/nacos/v1/ns/instance,参数如下:
- serviceName=服务名
- ip=服务IP地址
- port=服务端口号
发现接口GET:http://127.0.0.1:8848/nacos/v1/ns/instance/list,参数如下:
- serviceName=服务名
项目中实现服务注册于发现:
当然在项目中是不会手动模拟的,只需要一些简单配置就能自动完成这些。
服务提供者、调用者引入nacos-discovery依赖:
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
添加nacos注册中心的配置:
# 应用服务 WEB 访问端口 server: port:8080 spring: application: name: nacos-discovery-provider-sample # 应用名称 cloud: nacos: # Nacos帮助文档: https://nacos.io/zh-cn/docs/concepts.html discovery: # Nacos 服务发现与注册配置 username: nacos # Nacos控制台登录信息 password: nacos server-addr: 127.0.0.1:8848 # Nacos 服务器主机和端口 namespace: public # 注册到 nacos 的指定 namespace,默认为 public #config: # enabled: false # 不使用Nacos进行配置管理,默认true。 #默认使用nacos管理配置,这里先考虑仅作为注册中心的情况
此时,nacos已经引入,可使用注解@EnableDiscoveryClient来启用它:
@EnableDiscoveryClient @Configuration public class NacosDiscoveryConfiguration { }
在配置类启用和启动类启用的效果是一样的。配置好后启动服务,刷新控制台页面,服务注册了。
假设我们只想让nacos作为配置中心,而不做注册中心,只需要修改配置:nacos.discovery=false即可。
3.服务高可用、Nacos集群
Nacos服务搭建只需要下载并启动Nacos Server即可,在集群中也是如此,步骤如下:
- 准备多个Nacos server,并将端口区分开(不同主机就不用了);
- 所有nacos server都添加nacos/conf/cluster.conf文件:模板文件cluster.conf.example
# 所有nacos server的 IP:端口,包括自身 127.0.0.1:9848 127.0.0.1:9858 127.0.0.1:9868
- 分别进入bin目录,使用集群模式启动nacos
# 集群模式启动 startup.cmd -m cluster
注意:
- cluster.conf中不能使用localhost代替本机,否则报tomcat错误
- 集群必须使用mysql作为持久化
- 同一台主机,单机启动和集群启动不能共存,否则报tomcat错误。
- 集群模式下,不可以手动模拟服务注册。
配置好之后,可以发现每个nacos server 都能启动了,点击集群管理>节点列表就能看到其他nacos server了。
nacos集群有时也需要实现负载均衡,具体使用方法见文章尾部。
4.服务剔除机制、自我保护机制
服务每5s向注册中心发送心跳,证明自己还“活着”
5.数据持久化到MySQL
nacos除了注册中心外,还进行配置管理,在单机启动模式下,默认使用内嵌数据库,无需任何配置就能启动,内嵌式有一定局限,此处就不多说了。
但有时候我们需要将数据持久化到mysql ( 版本必须5.6.5+) ,只需要如下操作即可:
- 将nacos\conf\nacos-mysql.sql 文件执行到数据库中。
- 修改nacos\conf\application.properties配置文件,内容如下:
spring.datasource.platform=mysql # 使用的数据库 db.num=1 # 数据库数量 ### 连接: db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC db.user.0=root db.password.0=root
nacos支持多数据源,0表示第一个。配置完成后重启即可。
Eureka (AP)
Eureka满足CAP原理的AP,也满足Base理论。
1.搭建Eureka服务
创建eureka模块并添加依赖:eureka server
<!--引入EurekaService--> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>
yml配置:
server: #服务端口 port: 8081 #-------------------------eureka配置 eureka: instance: hostname: localhost client: register-with-eureka: false #是否将自己注册到注册中心 fetch-registry: false #是否从注册中心获取注册信息。 service-url: #配置暴露给Eureka Client的请求地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
注册中心本身也是一个服务,最后一行配置中,Eureka将自身地址暴露出去,服务调用者、服务提供者通过此地址来进行注册、调用。
开启Eureka服务:@EnableEurekaServer注解
@SpringBootApplication @EnableEurekaServer//激活eurekaService public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class,args); } }
到此,eureka服务就搭建好了,当然,调用者、提供者也需要一些配置才行。
2.服务注册与发现
服务注册,即我i服务将自身注册到注册中心,以供其它服务进行调用。
依赖:eureka client
<!--引入EurekaClient--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
配置文件中添加EurekaService的信息:
#eureka配置 eureka: client: service-url: defaultZone: http://localhost:8081/eureka/ #配置注册中心service地址 instance: prefer-ip-address: true #使用ip地址注册(可选)
可以使用 @EnableEurekaClient注解来开启服务客户端,当然可以省略。
暴露的地址IP+端口直接在浏览器访问Eureka控制台,可以看到服务信息。
如果想在控制台查看服务IP,则可以如下配置:
eureka: instance: prefer-ip-address: true #使用ip地址注册(可选) #向服务注册中心注册服务id instance-id: ${spring.cloud.client.ip-address}:${server.port}
3.服务高可用、Eureka集群
什么是高可用?高可用就是服务能够长久地提供服务。
注册中心也是服务,如果你只有一个注册中心服务,然后它挂了,那么整个服务将不可用。
保证高可用的原则是去单点化,实现集群化,即搭建多个Eureka服务,组成一个集群,其中一个宕机了,其它的可以进行替代。
搭建Eureka集群很容易,只须创建多个Eureka服务即可,注册中心也是服务,那么Eureka1和Eureka2相互注册,它们之间可以通过同步来达到数据的一致。(同步不是即时发生的,需要等一会才能在控制台看到)
实际的代码步骤如下:
常规的Eureka提供服务,需要暴露自己的地址,常规的服务注册需要获取Eureka服务的地址。
当Eureka1注册到Eureka2时,Eureka1充当服务的角色,且为其它服务提供服务注册功能,因此需要暴露自身的地址、配置注册中心地址(Eureka2)。因此配置如下:server: #服务端口 port: 8081 application: name: eureka-service #服务名 #eureka配置 eureka: instance: hostname: localhost #---------------------------------------------------暴露 # client: # register-with-eureka: false #是否将自己注册到注册中心 # fetch-registry: false #是否从注册中心获取注册信息。 # service-url: #配置暴露给Eureka Client的请求地址 # defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #--------------------------------------------------注册 client: service-url: #配置注册中心地址 defaultZone: http://localhost:8082/eureka/ #注册到8082 (2号)
当然通常的Eureka服务有3-5个,因此不可能注册到一个Eureka上,所以可以同时注册到多个注册中心:
defaultZone: http://localhost:8082/eureka/ http://localhost:8083/eureka/
可以看出,暴露端口的属性、注册的属性是一样的,但此处不影响,它将自动暴露所有eureka服务地址。
4.服务剔除机制、自我保护机制
服务剔除机制
Eureka有个服务剔除机制,默认为在Eureka服务上进行注册的服务,每30s向注册中心发送”心跳“,如果Eureka server超过90s未收到服务的心跳,则会识别该服务已宕机并自动将该服务剔除。
在每个服务中来设置心跳:
eureka: instance: prefer-ip-address: true #使用ip地址注册(可选) #向服务注册中心注册服务id instance-id: ${spring.cloud.client.ip-address}:${server.port} lease-renewal-interval-in-seconds: 33 #心跳间隔 lease-expiration-duration-in-seconds: 99 #到期时间
自我保护机制
Eureka可以根据服务心跳频率来保护服务,防止由于其它原因(如网络原因)导致未能及时发送心跳,但实际未宕机的服务被剔除。
Eureka服务配置:
eureka: server: enable-self-preservation: false #关闭自我保护 eviction-interval-timer-in-ms: 4000 #剔除服务间隔,单位ms
Consul (CP)
基于go语言,内置服务注册与发现框架、分布式协议实现、健康检查、key/value存储、多数据中心方案,使用较简单。支持http、dns协议接口。
Consul基于cp(强一致、分区容忍),在此集群中,主节点挂了,将暂时停止对外服务,选举出新的主节点后恢复可用。
1.搭建Consul服务
1.下载consul安装包: 官网: https://www.consul.io/
2.启动consul
#Dos命令:以开发者模式快速启动 consul agent -dev -client=0.0.0.0
参数:
- agent:启动一个consul的守护进程。
- dev:开发者模式
- client :consul代理,和consulService交互。一个微服务对应一个client,它们需要部署在一起。
- service:真正使用的consul服务,(3-5个)
3.管理后台:http://localhost:8500
2.服务注册与发现
将服务注册到consul,此时consul服务为注册中心。
服务若想将自身注册到服务注册中心,需如下配置:
为需要注册到consul的服务引入依赖:
<!--引入springCloud基于consul的服务发现--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <!--引入actuator的健康检查--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
为需要注册到consul的服务添加配置:
#开始配置consul的服务注册 spring: cloud: consul: host: localhost #注册的服务器地址 port: 8500 #ip地址 discovery: register: true #是否需要注册,默认为true instance-id: ${spring.application.name}-1 #注册的实例ID,-1为随便加的,用于区分 service-name: spring.application.name #服务名称 port: ${server.port} #服务端口 prefer-ip-address: true #是否开启ip地址注册 ip-address: ${spring.cloud.client.ip-address} #当前服务的ip地址
注意:上面的配置并非完整配置,服务名、端口等这里省略了,如果忘记了,可以参考Eureka章节的服务调用。
3.服务高可用、Consul集群
一个微服务对应一个client,consul强调数据一致性,保持微服务与所有service之间数据一致,使用了Gossip协议(流言协议)。
以下协议主要是为了保证注册中心集群中各节点数据保持一致:
Gossip协议:所有consul都参与gossip协议中(多节点中数据赋值)。详情
Raft协议:此过程有三个角色,详情
Leader :领导者,server集群中唯一处理客户端请求的。
Follower:选民,被动接收数据。
Candidate:候选者,可以被选为leader,即其它Consul。
consul集群的搭建步骤:
consul集群的范围是3-5台,低于3台则不会工作。
Linux上下载配置consul的命令:#从官网下载最新版本的Consul服务 wget https:releases.hashicorp.com/consul/1.5.3/consul_1.5.3_linux_amd64.zip #使用unzip解压 unzip consul_1.5.3_linux_amd64.zip #将解压好的consul可执行命令拷贝到/usr/local/bin目录下 cp consul /usr/local/bin #测试结果 consul
将三台主机分别安装并启动consul服务:
# Linux启动consul服务 consul agent -server -bootstarp-expect 3 -data-dir /etc/consul.d -node=server-1 -bind=S1的ip -ui ->client 0.0.0.0 &
参数:
- server:以server身份启动
- bootstarp-expect:集群里要求最少的server数量,数量比它低时,集群失效。
- data-dir :data存放的目录
- node:节点id,同一集群内不可重复。
- bind:监听的ip地址。
- client:客户端的ip地址,(0.0.0.0表示不限制)
- &:在后台运行,Linux脚本语法
选择一台作为主节点,并在其它两个节点执行如下操作即可:
# 添加到主节点 consul join 主节点ip
开发时,需要本地的consul也作为client注册到主节点,因为服务注册在本地的consul:
# 启动本地client consul agent -client=0.0.0.0 -data-dir /etc/consul.d -node=client-1 # 注册到主节点 consul join 主节点ip
如何查看有哪些节点呢?在任意一个节点执行如下操作即可:
# 查看集群节点信息 consul members
4.Consul的注册、发现、删除测试
此过程使用了api测试工具postman,它可以模拟客户端发送各种类型的请求。
服务注册测试:
实际上注册过程就是发送put请求到consul注册中心:http://localhost:8500/v1/catalog/register
发送的模拟数据如下:(body->raw->json)
{ "Datacenter":"dc1", "Node":"node01", "Address":"127.0.0.1", "Service":{ "ID":"mysql-01", "Service":"mysql", "tags":["master","v1"], "Address":"127.0.0.1", "port":3306 } }
服务发现:
响应为true,表示已经注册成功了,此时访问:http://localhost:8500 就能看到服务已被注册。
服务删除测试:
通过postman发送put请求到:http://localhost:8500/v1/catalog/deregister
发送的数据如下:
{ "Datacenter":"dc1", "Node":"node01", "ServiceID":"mysql-01" }
返回为true表示删除成功,刷新consul控制台就会发现服务已经被删除了。
5.健康检查
直接发送get请求查看服务健康信息:http://127.0.0.1:8500/v1/health/service/服务名
关于服务调用
Nacos、Eureka、Consul都直接集成了Ribbon,因此可直接使用Ribbon方式的服务调用。
服务调用的几种方式:https://blog.csdn.net/qq_52681418/article/details/113336593
关于注册中心的负载均衡
看到服务调用时,会发现Ribbon组件实现负载均衡,它是对多个相同的服务提供者之间实现负载均衡。
如上图,多个注册中心协调,有时也需要使多个注册中心的负载达到平衡状态,此时可以使用nainx来代理实现负载均衡。
使用Nginx实现注册中心负载均衡:
1.下载nginx,并在conf/nginx.conf中添加配置:在 http{ } 块中添加
#配置代理服务器的地址,即Nginx安装的服务器地址、监听端口、默认地址 upstream nacos{ server 127.0.0.1:9848 weight=2; server 127.0.0.1:9858 weight=1; server 127.0.0.1:9868 weight=1; }
参数:
- weigth参数表示权值,权值越大,分配负载
- down表示不参与负载
- backup,备用,其它机器忙时才用它
配置nginx服务:在server{ }块中配置
# 配置nginx服务 server { listen 9099; #1.监听端口,即访问的端口 server_name localhost; #服务名:对于server_name,如果需要将多个域名的请求进行反向代理,可以配置多个server_name来满足要 #对上面三台nacos进行代理 location /nacos/ { proxy_pass http://nacos; } ... }
双击启动nginx,浏览器访问:http://localhost:9099/nacos/ 就能访问了,而且服务注册的地址也可以填这个。多次刷新nacos控制台,可以发现当前使用的nacos server是变化的: