Eureka 采用 CS(Client/Server,客户端/服务器) 架构,它包括以下两大组件:
- Eureka Server:Eureka 服务注册中心,主要用于提供服务注册功能。当微服务启动时,会将自己的服务注册到 Eureka Server。Eureka Server 维护了一个可用服务列表,存储了所有注册到 Eureka Server 的可用服务的信息,这些可用服务可以在 Eureka Server 的管理界面中直观看到。
- Eureka Client:Eureka 客户端,通常指的是微服务系统中各个微服务,主要用于和 Eureka Server 进行交互。在微服务应用启动后,Eureka Client 会向 Eureka Server 发送心跳(默认周期为 30 秒)。若 Eureka Server 在多个心跳周期内没有接收到某个 Eureka Client 的心跳,Eureka Server 将它从可用服务列表中移除(默认 90 秒)。
比较官方的语言,我们还是通俗易懂的来讲一下这个东西,其实就相当于,因为我们使用微服务是把每一个服务单独进行管理,单独管理就会出现需要数据直接的通信问题,例如:商品的仓库是一个服务,售卖产品也是一个服务,但现在放在不同的地方,所以假如卖出一件商品,就需要告诉仓库,应该减少一件产品,这样就达到了微服务的思想,而我们之前所了解的springboot就不一样,springboot是将所有的服务都集中在一起管理。
讲解完后,我们正式进行Eureka的配置和使用的讲解
说真的,讲了很多的配置,这个配置确实算是比较复杂,而且出现问题的地方可能有很多,一定要注意很多细节的处理,不然有可能服务都能启动就是挂载不上的也有可能出现的,接下来我们先配置最基本启动Eureka的服务配置
创建基本项目、导包
第一个我们创建项目,首先创建都是基于marven来管理的
这里有个坑,这个URL的网址有时候会有问题,等一会儿就好了,或者重启一下idea,还有是可以换成阿里巴巴的URL,不过很多时候是正常的,建项目完成后,我们在当中在导入modules,导入的modules就使用spring Initializr的
构建完成这个项目后,可以把父文件中的pom文件都删除,因为我们配置的pom都是在每一个独立的服务中
我们创建springboot项目的时候,可以勾选后就自定帮助我们把包可以自动的讲包依赖在我们的pom文件中,你可以不勾选,因为下面我都会告诉你需要导入的jar包有哪些。
我们构建三个服务,一个是配置服务,另一个是提供者(相当于接口的提供者),另一个是消费者(相当于调用接口)。
配置Eureka服务
第一个配置:使用modules导入进来后,进入pom文件下,导入我们需要的包
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo1</name>
<description>demo1</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
我这个是最新的springBoot和spirngCloud所以不会出现版本不兼容的问题,但是这里的坑就在于,很多朋友可能就是因为版本兼容的问题,所以这里是会出错的,如果想了解什么样的springBoot可以配置什么样的springCloud可以在marven的官网查看spring-boot-starter去搜索一下就会出来了。一定要看清楚,和我配置的一样不,不然就会爆红或者报错了,还有就是注意,导入进来后,记得刷新一下marven这样才会下载jar包进来
这里也就是我们的pom文件的配置,下面我们需要配置yml文件对eureka中的具体做配置,创建一个application.yml文件,如果不是绿叶的,可以去看下我写的另一篇文章 SpringBoot绿叶显示yml和端口问题
创建完成之后在里面配置如下信息
server:
port: 8087
spring:
application:
name: demo1
eureka:
instance:
hostname: localhost #hostname是eureka集群服务器之间的区分
client:
registerWithEureka: false #不向自身注册。由于该应用为单个注册中心,所以设置为false,代表不向注册中心注册自己
fetchRegistry: false #不从自身拉取注册信息。由于单个注册中心,不拉取自身信息
server:
enableSelfPreservation: false # eureka 的自我保护状态:心跳失败的比例,在15分钟内是否超过85%,如果出现了超过的情况,Eureka Server会将当前的实例注册信息保护起来,同时提示一个警告,一旦进入保护模式,Eureka Server将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据。也就是不会注销任何微服务。测试阶段将其关闭
这里注意的点是,配置的hostname就是需要访问的地址,就是注册中心的名字,其他的配置属性看看是什么意思,都有注释的
配置完成后,我们在springboot的启动项上添加注解@EnableEurekaserver,导入完成之后,我们的服务就是可以跑起来的了,启动项目,在网页中打开http://localhost:8087(我这里配置的端口号为8087),就看到下面这个画面
箭头这里看到,还没有实例的服务进来,所以我们接下来就可以开始配置消费者和提供者了。
配置提供者(提供接口)
我们在父级的目录在添加一个marven的modules,构建完基础的,我们直接讲解配置
配置提供者的pom文件, 如下是配置信息
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo2</name>
<description>demo2</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
一定要看清,我这里配置的是spring-cloud-starter-netflix-eureka-client的,和刚刚spring-cloud-starter-netflix-eureka-serve是不一样的,在配置完pom文件后,我们在配置当中的application.yml文件
server:
port: 8082
eureka:
client:
registerWithEureka: true
fetchRegistry: true
service-url: # eureka server 的地址, 咱们单实例模式就写自己好了
defaultZone: http://localhost:8087/eureka
spring:
application:
name: demo2
这里有坑注意
①我们可能会因为版本号的原因导致service-url爆红,并且defaultZone会没有,但是没关系,直接复制过去我的就可以用了
②registerWithEureka的设置要改为true,因为刚刚是服务不用自我去注册和下面的fetchRegistry拉取自身信息,但是现在已经是要用了,就不是提供的服务了,所以需要该问true
③spring-application-name要填,这样方便在Eureka的网站中更清楚的看到有没有注册进来
④在defaultzone中连接的名字为刚刚启用服务的名字,后面需要/eureka
我们写完这些后,因为我们这里写的是提供者,所以还需要写一个接口,直接写一个Controller
package com.example.demo2.controll;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controll {
@GetMapping(value = "/hello")
public String index() {
return "hello provider";
}
}
我们还需要配置最后的主类,在主类中配置如下
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class Demo2Application {
public static void main(String[] args) {
SpringApplication.run(Demo2Application.class, args);
}
}
这样的话就是可以使用了,我们启动一下,测试看看能不能在Eureka中找到这个名为demo2的服务
这样就可以看到多了一个服务叫做Demo2的服务
配置消费者(调用接口)
这个调用接口中,我们会使用到RestTemplate的用法,如果不了解,可以看下我的这篇Java中使用RestTemplate
一样的,我们先构建modules后,配置当中的pom文件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo3</name>
<description>demo3</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
这个的配置和提供者的配置pom文件一致,都是服务所以一致,因为在Eureka中可以充当提供者也可以充当消费者。下面配置的是application.yml文件
server:
port: 8089
spring:
application:
name: demo3
eureka:
client:
registerWithEureka: true
fetchRegistry: true
service-url: # eureka server 的地址, 咱们单实例模式就写自己好了
defaultZone: http://localhost:8087/eureka
instance:
status-page-url: http://localhost:8082/hello
这里讲解坑的地方
①一样的,regsiterWithEureka和fetchRegistry需要设置为true
②我这里多配置了一个instance-status-page-url,这是配置的我们需要跳转的网址,我们就是通过这种方式,可以在不同的端口下进行相互的访问,也就可以通过发送请求和获取数据达到数据传输的效果
下面我们写发送请求
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
public class Contros {
@Resource
RestTemplate restTemplate;
@RequestMapping("/hello")
public String hello(){
return restTemplate.getForEntity("http://localhost:8082/hello",String.class).getBody();
}
}
可能有人会问,为什么刚刚已经写了和这个getForEntity后面一模一样的地址,这个其实是因为,在yml文件中配置的我们可以在Eureka中直接点击网址就可以跳转,没有设置的话,是不会跳转的,这里的话就是真实的发起请求的路径。
之后我们配置主类
@SpringBootApplication
@EnableDiscoveryClient
public class Demo3Application {
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Demo3Application.class, args);
}
}
这里有一个@Bean下和@LoadBalanced的注解下写了返回一个发请求的RestTemplate,这是我们依赖注入RestTemplate并且@LoadBalanced(负载均衡)是系统处理高并发、缓解网络压力和服务端扩容的重要手段之一。
启用服务,会发现下图所示
我们可以看见我们刚刚配置yml中的作用就在这里,我们是可以访问Demo2的接口的,直接点击一下就可以跳转到我们调用的接口中了
Ribbon
负载均衡(Load Balance) ,简单点说就是将用户的请求平摊分配到多个服务器上运行,以达到扩展服务器带宽、增强数据处理能力、增加吞吐量、提高网络的可用性和灵活性的目的。
常见的负载均衡方式有两种:
- 服务端负载均衡
- 客户端负载均衡
服务端负载均衡
服务端负载均衡是最常见的负载均衡方式,其工作原理如下图。
图1:服务端负载均衡工作原理
服务端负载均衡是在客户端和服务端之间建立一个独立的负载均衡服务器,该服务器既可以是硬件设备(例如 F5),也可以是软件(例如 Nginx)。这个负载均衡服务器维护了一份可用服务端清单,然后通过心跳机制来删除故障的服务端节点,以保证清单中的所有服务节点都是可以正常访问的。
当客户端发送请求时,该请求不会直接发送到服务端进行处理,而是全部交给负载均衡服务器,由负载均衡服务器按照某种算法(例如轮询、随机等),从其维护的可用服务清单中选择一个服务端,然后进行转发。
服务端负载均衡具有以下特点:
- 需要建立一个独立的负载均衡服务器。
- 负载均衡是在客户端发送请求后进行的,因此客户端并不知道到底是哪个服务端提供的服务。
- 可用服务端清单存储在负载均衡服务器上。
客户端负载均衡
相较于服务端负载均衡,客户端服务在均衡则是一个比较小众的概念。
客户端负载均衡的工作原理如下图。
图2:客户端负载均衡工作原理
客户端负载均衡是将负载均衡逻辑以代码的形式封装到客户端上,即负载均衡器位于客户端。客户端通过服务注册中心(例如 Eureka Server)获取到一份服务端提供的可用服务清单。有了服务清单后,负载均衡器会在客户端发送请求前通过负载均衡算法选择一个服务端实例再进行访问,以达到负载均衡的目的;
客户端负载均衡也需要心跳机制去维护服务端清单的有效性,这个过程需要配合服务注册中心一起完成。
客户端负载均衡具有以下特点:
- 负载均衡器位于客户端,不需要单独搭建一个负载均衡服务器。
- 负载均衡是在客户端发送请求前进行的,因此客户端清楚地知道是哪个服务端提供的服务。
- 客户端都维护了一份可用服务清单,而这份清单都是从服务注册中心获取的。
Ribbon 就是一个基于 HTTP 和 TCP 的客户端负载均衡器,当我们将 Ribbon 和 Eureka 一起使用时,Ribbon 会从 Eureka Server(服务注册中心)中获取服务端列表,然后通过负载均衡策略将请求分摊给多个服务提供者,从而达到负载均衡的目的。
Ribbon 可以与 RestTemplate(Rest 模板)配合使用,以实现微服务之间的调用。
RestTemplate 是 Spring 家族中的一个用于消费第三方 REST 服务的请求框架。RestTemplate 实现了对 HTTP 请求的封装,提供了一套模板化的服务调用方法。通过它,Spring 应用可以很方便地对各种类型的 HTTP 请求进行访问。
RestTemplate 针对各种类型的 HTTP 请求都提供了相应的方法进行处理,例如 HEAD、GET、POST、PUT、DELETE 等类型的 HTTP 请求,分别对应 RestTemplate 中的 headForHeaders()、getForObject()、postForObject()、put() 以及 delete() 方法。
最后总结
我们这里主要的配置文件和主要调用的API,都是在Eureka中会常常使用的,我们还可以 在当中配置更多的接口和发起更多的请求,这样就达到我们独立的模块,但却可以将数据共享出来的效果,这也就是SpringCloud的重要思想,但我们所讲的这种是单例的,并不是集群的,还有就是Ribbon了解主要解决了什么问题就可以了,先了解,后深入
版权归原作者 全栈Demo 所有, 如有侵权,请联系我们删除。