学习Eureka之前,我们先来说一下微服务中常用的两个术语。
服务提供者:一次业务中,被其他微服务调用的服务。(提供接口给其他服务)
服务消费者:一次业务中,调用其他服务的服务。(调用其他服务的接口)
切记,提供者和消费者是针对一次业务进行划分的。
前面的案例中,order就是消费者,user就是提供者。
注意:一个服务,既可以是消费者,也可以是提供者,当然也可以同时是提供者,也是消费者。比如,A调用B,B调用C,那么B对A而言就是提供者,B对C而言,就是消费者。
服务调用出现的问题:
1、服务消费者该如何获取服务提供者的ip地址信息?
2、如果有多个服务提供者,消费者该如何选择?
3、消费者如何得知提供者的健康状态?
前面我们的小Demo,使用的是RestTemplate发送Http请求的方式,请求另一个服务,但是这种写法有一个问题,我们在公司的时候,其实会有各种环境,最简单的就是划分为生产环境和测试环境,而生产环境和测试环境,那么,我们每次部署,都要修改编码和打包,显然不实际。(问题1)
而各个环境下又不太可能说只有一台服务器,如果只有一台,那他炸了,岂不是完全裂开了,这个时候,我们的ip地址又应该怎么去写?该用哪台服务器的ip地址?(问题2、问题3)
Eureka有两个角色:
一个是服务端:eureka-server,注册中心,负责记录和管理我们的微服务
一个是客户端:eureka-client,他包括我们的提供者和消费者,在前面的demo中,他应该包含我们的user和order。
假如我们的提供者user现在有三台服务器部署(用三个端口号代替),分别是8081、8082、8083,我们的order只有一台服务器部署,8080,我们先在eureka的服务端进行服务信息的注册,每次当order请求的时候,eureka服务端都会把user的ip地址拉取下来给order,消费者利用负载均衡算法,从服务列表挑选一个,进行远程调用。
注册的服务器每30秒回向eureka发送一次心跳,当服务器出现宕机,那么他的ip地址也会被eureka服务端剔除掉,即当其他服务向其发送请求的时候,不将宕机的服务器的ip地址发送给提供者。
以下图片来源于B站黑马程序员的SpringCloud教程!!!
以下图片来源于B站黑马程序员的SpringCloud教程!!!
以下图片来源于B站黑马程序员的SpringCloud教程!!!
步骤一、搭建注册中心
首先,在我们的demo目录下,再新建一个Moodle,用Maven工程创建(不要用Spring初始化),不做过多介绍,然后修改他的pom.xml文件如下:
<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>demoartifactId>
<groupId>org.examplegroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>eureka-serverartifactId>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
dependencies>
project>
然后我们写我们的Application。
EurekaApplication.java:
package com.example.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
之后写我们的配置文件:
application.yaml
#服务端口
server:
port: 8090
#服务名称(服务名称不要掺杂大写,会识别不了的!!!)
spring:
application:
name: eurekaserver
#eureka地址信息
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8089/eureka
这里,因为eureka也是一个微服务,所以,我们要配置eureka的地址信息,将他自己也注册到eureka上。
写完,我们启动eureka服务器,然后访问本机的8090端口,可以看到:
上图框中部分,是Eureka最重要的部分之一,其中,EUREKASERVER是服务的名称,Status是服务的状态,UP表示正常,DOWN表示宕机,后面DESKTOP-95D7VP6是我的是计算机名(Windows的问题),如果是Linux服务器的话,那么这一块应该是 ip地址:服务名:端口号 的。
步骤二、服务注册
将user和order服务注册到EurekaServer注册中心,只需要以下两步
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
#服务名称
spring:
application:
name: user
#eureka地址信息
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8090/eureka
在order的application.yaml文件下也一样:
#服务名称
spring:
application:
name: order
#eureka地址信息
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8090/eureka
完事后,我们再次启动user和order服务,进入我们的8090端口,可以看到。他们都被注册进去了
这里,我们可以看到,Order和User都只注册了一个服务,我们借助 JVM 和 IDEA, 再复制一个User服务看一下。在Services中,右键UserApplication,选择Copy Configuration…
在VM options输入框中输入JVM命令:
点击Apply,Ok,在Services下,我们可以看到,多了个UserApplication(1),我们也把他启动起来。
此时,再看我们的Eureka如下:(可以看到USER这个服务下面,多了一个计算机名:端口号)
扩展:如何删除Eureka注册中心已经注册的服务?
简单,使用我们的Postman或者Postwoman都行,发送一条Delete请求如下:
http://localhost:8090/eureka/apps/USER/DESKTOP-95D7VP6:user:8082
那么这个请求的格式是啥嘞,其实很简单啊,请看下图:
步骤三、服务发现
服务发现分为两步走:
1、修改访问的url路径名,用Eureka中注册的服务名代替我们固定的ip加端口号
以我们的Order为例,还是请求我们的user服务,此时OrderService中的方法应改写为:
public Order selectById(Long id) {
//1、获取订单信息
Order order = orderMapper.selectById(id);
//2、利用RestTemplate获取http请求(第一个user是服务名,第二个user对应的是GetMapping的值)
String url = "http://user/user/"+order.getUserId();
/**
* getForObject方法
* 第一个参数是请求的url
* 第二个参数是预封装的实体类
*/
User user = restTemplate.getForObject(url, User.class);
//3、封装到order
order.setUser(user);
return order;
}
2、在RestTemplate添加负载均衡注解
@Configuration
public class MyConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}