注册中心
什么是注册中心
这里做一个简单的类比
三个实体:
景区:提供服务,通过114注册联系信息
114查号台:负责收录各个景区提供的服务和联系信息,一旦景区电话号发生更改
游客:游览景区,通过114查到景区号码,然后拨打景区电话调用服务
微服务中的注册中心的功能就是114查号台。
有关服务中心的三个实体:
1. 服务提供者Server:一次业务中,被其他微服务调用,也就是对外提供服务者,它会向服务中心注册服务实例,以及URL(可以理解为联系方式),这就是服务注册
2. 服务消费者Client:一次业务中,调用其他微服务,也就是享受服务者,它会先查询注册中心找到对应服务的URL,这就是服务发现,然后调用URL进行调用
3. 服务注册中心Registry:用于保存Server的注册信息,当Server节点发生变更,Registry会同步变更。服务和注册中心使用一定的通信机制例如心跳机制,如果注册中心长时间无法和服务提供者保持联络,就会自动销毁这个服务实例
CAP理论
CAP理论是分布式系统中最基础,也是最关键的理论
C:consistency,一致性,这里的一致性指的是强一致性
A:ability,可用性,对于所有请求都会做出相应,无论对错
P:partition tolerance:分区容错性,在网络分区的情况下仍然可以提供服务
CAP三者无法同时满足,比如,进行一次修改,需要所有节点同步。如果保证可用性,那么暂时没有被同步的节点为了保证可用性,会传回错误信息;如果保证一致性,那么必须所有未更新节点停止对外服务,等待同步完成再重新提供服务
在开发中,P必须满足,而C和A根据业务需要灵活取舍,也就是灵活选择CP架构或者AP架构
常见的注册中心
1. Zookeeper
国内的Java体系,大多集群环境都是依靠zookeeper进行注册功能的开发
2. Eureka
基于NetFlix公司的REST服务开发框架,可以用于服务注册与管理,负载均衡,服务故障转移等工作
3. Nacos
是阿里巴巴的重要组件,除了服务注册,服务发现之外,Nacos还提供配置管理,流量管理,DNS等功能
Eureka简单实现
上一篇文章中,我们创建了两个基于SpringBoot的微服务8080: order-service和、
9090: product-service
我们的目标是前端请求order-service微服务,然后order-service微服务调用product-service微服务,获取product的详细信息,最后由order-service传回包括product的order详细信息。
我们已经成功的搭建了微服务之间的调用,但是问题是URL是写死的,不便于维护和扩展,下面我们将基于Eureka进行改进
Eureka服务的编写
在父工程中创建子工程Eureka,然后修改配置文件pom.xml
<?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"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.spring</groupId> <artifactId>springcloud-Euraka</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>eureka</artifactId> <properties> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>随后,修改Eureka服务的application.yml文件
这里要注意,因为我们用本机演示,所以每个微服务的端口号须保持不同,否则会引起端口号冲突
# Eureka相关配置 # Eureka 服务 server: port: 10010 #端口号 spring: application: name: eureka-server eureka: instance: hostname: localhost #ip地址 client: fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为false register-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false. service-url: # 设置Eureka Server的地址,查询服务和注册服务都需要依赖这个地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/随后,按照图示架构重构Eureka模块:
启动Eureka
服务注册——product-service
1. 加入Eureka的依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>2. 修改配置信息
#Eureka Client eureka: client: service-url: defaultZone: http://127.0.0.1:9090/eureka/3. 启动测试
输入我们配置的IP+端口号后,可以看到进入了Spring的Eureka服务
在Eureka服务中,我们可以看到我们的product实例:
服务发现——order-service
1. 加入Eureka的依赖
同样的步骤:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>2. 修改配置信息
server: port: 8080 spring: application: name: cloud-order datasource: url: jdbc:mysql://127.0.0.1:3306/cloud_order?characterEncoding=utf8&useSSL=false username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*Mapper.xml configuration: # 配置打印 MyBatis 执行的 SQL log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true #自动驼峰转换 #Eureka Client eureka: client: service-url: defaultZone: http://127.0.0.1:10010/eureka/3. 修改远程调用的service代码
public OrderInfo selectOrderInfoById(Integer orderId) { OrderInfo orderInfo = orderMapper.selectOrderInfoById(orderId); // String url="http://127.0.0.1:9090/product/selectProductInfoByProductId?productId="+orderInfo.getProductId(); //根据“clout-product”服务名称,从eureka获取服务 List<ServiceInstance> instances = discoveryClient.getInstances("cloud-product"); //因为我们只有一个服务实例,所以直接get(0)获取URI String uri = instances.get(0).getUri().toString(); log.info("uri:{}",uri); //拼接URL String url = uri + "/product/selectProductInfoByProductId?productId=" + orderInfo.getProductId(); log.info("url:{}",url); //获取、填充product信息 ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class); orderInfo.setProductInfo(productInfo); return orderInfo; }4. 启动测试
刷新网站后我们可以看到,Eureka已经启动了两个微服务实例
此时,我们就可以基于Eureka进行微服务之间的调用了。