阅读提示:
本文是SpringCloud系列第二篇,请先阅读前置文章。
所有代码都基于01认识微服务,了解服务拆分与远程调用中的基础代码cloud-demo,可以前往下载。
一、问题引入
在上一篇文章中,我们在OrderService类的queryOrderById方法里,使用RestTemplate里向user-service微服务发起调用请求,根据用户id查询用户信息,代码如下:
// 2.使用RestTemplate发起http请求 实现远程调用
String url = "http://localhost:8081/user/"+order.getUserId();
User user = restTemplate.getForObject(url, User.class);
当前存在的问题
在微服务中,往往一个服务模块如这里的user-service服务,会部署在多台机器上以应对高并发访问,因此会有多个实例及地址,以本机部署三个user-service服务为例,它们的端口号分别为8081,8082,8083,如下图:
那么这时我依然使用之前的RestTemplate发起访问请求,会存在以下几个问题:
// 2.使用RestTemplate发起http请求 实现远程调用
String url = "http://localhost:8081/user/"+order.getUserId();
User user = restTemplate.getForObject(url, User.class);
-
user-service实例的ip地址和端口变化时,order-service该如何得知?
很显然目前我们只能把user-service实例的地址写死在order-service的配置文件中,当user-service实例的地址和端口变化,也要修改order-service的配置文件,说不定还有很多其他微服务,也要调用user-service,当不得已修改user-service实例的地址和端口时,重新部署非常麻烦。 -
有多个user-service实例的地址时,order-service该选择哪一个?
1.首先固定选择其中某一个实例,肯定是不合适,因为只要这个user-service实例宕机,调用它的order-service实例也就宕机了,会影响微服务架构的稳定性、可用性。
2.那么该怎么选择呢?这很难选,因为order-service不知道哪一个实例是健康的,哪一个已经宕机;或者哪一个当前服务器资源比较紧张,暂时不应该访问的(负载均衡)。而且RestTemplate的url地址是写死的,虽然可以在运行过程中修改url地址,但还是回到了问题本身,不清楚该选择哪一个。
二、Eureka的结构与作用
上述问题都需要利用SpringCloud中的注册中心来解决,其中最广为人知的注册中心就是Eureka,其结构如下:
回答上述两个问题。
-
user-service实例的ip地址和端口变化时,order-service该如何得知?
user-service服务实例启动后,将自己的信息注册到eureka-server(Eureka服务端),这个叫服务注册。
eureka-server保存服务名称到服务实例地址列表的映射关系。
order-service根据user-service服务名称,拉取其实例地址列表。这个叫服务发现。
在这种服务注册与发现的方式下,order-service甚至不需要把user-service的具体地址写入自己的配置文件中,只需要在访问user-service时,去Eureka服务端拉取目前的user-service服务实例的地址即可。 -
有多个user-service实例的地址时,order-service该选择哪一个?
使用@LoadBalanced注解,让order-service从user-service的实例列表中利用负载均衡算法选择其中一个实例地址;并且user-service的实例会定时向Eureka服务端发送心跳,超过一定时间没有发送心跳时,eureka-server会认为微服务实例故障,将该实例从服务列表中剔除,order-service拉取服务时,就能将故障实例排除了,这就保证了order-service选择user-service实例时,既能保证保证均衡,又能保证排除故障实例。
因此注册中心解决的主要问题就是微服务之间进行远程调用时,让微服务之间能够互相发现对方,同时一定程度上可以监测微服务的健康状态,并提供负载均衡的功能,归根到底解决的就是远程调用时选择哪个实例这一个问题。
注意: 一个微服务,既可以是服务提供者,又可以是服务消费者,因此eureka将服务注册、服务发现等功能统一封装到了eureka-client端,且每个微服务启动时都会将自己注册到Eureka服务端中。
三、搭建Eureka-server
首先搭建注册中心服务端:eureka-server,这必须是一个独立的微服务。
在cloud-demo模块下,创建一个子模块maven工程,命名为eureka-server。
引入SpringCloud为eureka提供的starter依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
给eureka-server服务编写一个启动类,一定要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能:
package cn.itcast.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
编写配置文件application.yml,内容如下:这里我们设置eureka-server的ip为本机的10086端口
server:
port: 10086
spring:
application:
name: eureka-server
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
启动微服务EurekaApplication,然后在浏览器访问:http://127.0.0.1:10086
看到下面结果就是成功了:
四、服务注册与发现
前面已经说过,一个微服务既可以是服务的提供者,也可以是服务消费者,因此只需要使用同一个依赖spring-cloud-starter-netflix-eureka-client,就可以同时实现一个微服务的注册与发现。
4.1 配置user-service
(1) 引入依赖
在user-service的pom文件中,引入下面的eureka-client(eureka客户端)依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2) 修改配置文件
在user-service中,修改application.yml文件,添加服务名称、eureka地址:
后续其他服务要访问user-service,就是通过这个服务名称来发起请求,因此这里命名最好规范。
spring:
application:
name: userservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
(3) 使用IDEA启动多个user-service实例
首先,右键复制原来的user-service启动配置:
修改运行实例名称为UserApplication2,点击Modify options,点击Add VM Options
接着填写-Dserver.port=8082来修改运行端口号
启动两个User-service实例,可以在eureka控制台看到如下信息:
4.2 配置order-service
之前说过,服务发现、服务注册统一都封装在eureka-client依赖,因此引入依赖和与配置文件的修改和user-service基本一致。
(1) 引入依赖
在order-service的pom文件中,引入下面的eureka-client依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
(2) 修改配置文件
在order-service中,修改application.yml文件,添加服务名称、eureka地址
spring:
application:
name: orderservice
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
(3) 服务拉取与负载均衡
负载均衡的设置
在order-service的OrderApplication中,给RestTemplate这个Bean添加一个@LoadBalanced注解:
/**
* 创建RestTemplate并注入Spring容器
* @return
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
服务拉取
修改order-service服务中的cn.itcast.order.service包下的OrderService类中的queryOrderById方法。修改访问的url路径,用服务名userservice代替ip+端口的url
public Order queryOrderById(Long orderId) {
// 1.查询订单
Order order = orderMapper.findById(orderId);
// 2.使用RestTemplate发起http请求 实现远程调用
String url = "http://userservice/user/"+order.getUserId();
User user = restTemplate.getForObject(url, User.class);
// 封装到order中
order.setUser(user);
// 4.返回
return order;
}
@LoadBalanced注解可以让RestTemplate能够识别服务的名称而不是直接使用URL。这样,发送HTTP请求时,RestTemplate会根据服务名称来选择一个可用的实例进行调用。它会根据负载均衡策略,在多个实例之间分配请求,以达到负载均衡的效果,当然前提是结合注册中心使用。
详细原理请阅读:https://zhuanlan.zhihu.com/p/617967367文章来源:https://www.toymoban.com/news/detail-754156.html
4.3 效果测试
重新启动OrderApplication,浏览器访问localhost:8080/order/101,可以发现IDEA控制台中8081和8082端口的UserApplication服务轮流打印信息,因此注册中心部署和服务注册、发现,负载均衡都成功实现。文章来源地址https://www.toymoban.com/news/detail-754156.html
到了这里,关于【SpringCloud】02 注册中心Eureka的原理与使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!