Spring Cloud应用- Eureka原理、搭建

初期对Spring Cloud的学习以应用搭建为主,所以内容不会太枯燥。

一直以来,自以为Spring全家桶的学习中,Spring framework是基础中的基础,部分内容也还是必须要读源码去理解底层原理,SpringMVC、SpringBoot,甚至Mybatis等等,都是如此。但是对于Spring Cloud来说,就从应用入手,以系统搭建为主。以此作为目标的话,Spring Cloud比其他几个部分来讲就会简单很多。

Spring Cloud的几大组件依次学习,先从Eureka入手。Eureka是netflix的服务治理组件,提供服务注册和服务发现、实现注册中心服务。

Eureka包含server端和client端。

Eureka server:服务端,也就是注册中心,每一个Eureka客户端需要向服务端注册,注册成功后服务端持有客户端列表,客户端定时发送心跳至服务端、汇报健康状态,超时未发送心跳服务的客户端将从注册中心的客户端列表中清除。

Eureka client:使用端、客户端,包括服务提供者server provider和服务消费者server consumer,不论服务提供者还是服务消费者,都要向Eureka服务端进行注册并定时发送心跳。服务消费者向服务端获取一份服务提供者的列表、在需要服务提供者服务的之后,向服务提供者发起服务请求并获取服务。

与Spring Boot版本的兼容

Spring Cloud基于SpringBoot搭建,在搭建Spring Cloud项目的时候需要注意Spring Cloud和SpringBoot之间的版本兼容关系,两者之间版本能兼容的情况下,搭建Spring Cloud项目其实并不复杂。否则如果版本不兼容,会出现各种莫名其妙的错误。

在这里插入图片描述

具体的版本对应关系请参考Spring官网:https://spring.io/projects/spring-cloud。

项目结构

我们用一个例子来学习Spring Cloud的Eureka组件,例子项目包含一个父项目、一个Eureka注册中心(Eureka server)Module、一个orderService(Eureka client,service consumer)module、一个userService(Eureka client,service provider)。

其中Eureka注册中心作为Eureka的服务端,所有的Eureka client都要向注册中心进行注册。

orderService模块模拟订单模块,作为微服务,是Eureka的客户端,启动后需要向注册中心进行注册。

userService模拟用户模块,作为微服务,是Eureka的客户端,启动后需要向注册中心进行注册。

orderService需要通过访问userService获取用户信息,这种情况下,orderService就是服务消费者,userSerivce是服务提供者,作为Eureka的客户端,两者都会从注册中心获取到Eureka客户端的信息,因此可以非常方便的访问到彼此:orderService当然能访问到userService提供的服务。

本案例的目的是搭建Spring Cloud的Eureka环境,不做具体的业务实现,也没必要进行数据库的访问、没必要做接口访问的鉴权…等等,所有相关业务细节均忽略。

好的,开始搭建环境。

父项目

创建SpringBoot工程,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><packaging>pom</packaging><modules><module>eureka-service</module><module>userService</module><module>orderservice</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>springCloud</artifactId><version>0.0.1-SNAPSHOT</version><name>springCloud</name><description>springCloud</description><properties><java.version>17</java.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!--SpringCloud 版本号2021.0.8--><spring.cloud.version>2021.0.8</spring.cloud.version></properties><dependencyManagement><dependencies><!--spring cloud依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring.cloud.version}</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>

父工程不需要有代码,所以,删除掉src目录。

注意选用的SpringBoot版本号为2.6.5,对应的Spring Cloud的版本号为2021.0.8,需要注意对照官网查询两者的兼容性。

注册中心模块

创建eureka注册中心模块,命名为eureka-service,pom文件中引入spring-web与eureka-service组件:

<?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"><parent><artifactId>springCloud</artifactId><groupId>com.example</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>eureka-service</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><!--spring-cloud-starter-netflix-eureka-server 依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><!--spring-boot-starter-web 依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies></project>

在resource下创建application.yml配置文件:

# eureka server
server:port: 10086# eureka server
eureka:instance:hostname: localhost  # eureka服务名client:registerWithEureka: false #是否向注册中心注册自己fetchRegistry: false # 是否向注册中心获取注册信息serviceUrl: #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/server:enableSelfPreservation: false # 自我保护

设置服务名称为localhost,端口号为10086,设置注册中心的访问地址为http://localhost:10086/eureka/

其实可以发现Eureka注册中心服务其实就是一个web服务,由tomcat提供服务。

创建启动类:

package com;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);}
}

启动类增加注解@EnableEurekaServer,表明当前服务是Eureka的注册中心。

运行启动类,服务正常启动后,浏览器输入http://localhost:10086访问Eureka服务:
在这里插入图片描述
可以看到服务已经正常启动,不过当前尚未有任何客户端注册。

userservice

创建userserice模块,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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springCloud</artifactId><groupId>com.example</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>userService</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies></project>

引入spring-cloud-starter-netflix-eureka-client以及spring-boot-starter-web即可。

在resource下创建application.yml文件:

spring:application:name: userservice  # eureka服务名称
eureka:client:service-url: # eureka注册中心路径defaultZone: http://127.0.0.1:10086/eureka/
server:port: 8080

指定当前应用的name,并配置eureka注册中心路径。并指定当前服务的端口号8080。

启动类加入@EnableEurekaClient注解,表明当前应用是eureka client:

package com;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication {public static void main(String[] args) {SpringApplication.run(UserServiceApplication.class);}
}

然后创建一个User类,简单一点,只包含一个属性name即可:

package com.example.entity;import com.fasterxml.jackson.annotation.JsonCreator;
import lombok.Data;@Datapublic class User {private String name;
}

创建一个UserController,提供一个/user/getUser的访问,为了能够在测试的时候反馈具体是哪一个userservice提供了服务,log打印一句话,创建一个User对象返回即可。

package com.example.controller;import com.example.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/user")
@Slf4j
public class UserController {@GetMapping("/getUser")public User getUser(){log.info("userController's getuser comming......");User user=new User();user.setName("zhangsan");return user;}
}
orderservice

创建orderservice模块,pom文件与userservice模块大致相同:

<?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"><parent><artifactId>springCloud</artifactId><groupId>com.example</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>orderservice</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.example</groupId><artifactId>userService</artifactId><version>0.0.1-SNAPSHOT</version></dependency></dependencies></project>

application.yml文件,指定端口号9090:

spring:application:name: orderservice
eureka:client:service-url: # eureka ?????defaultZone: http://127.0.0.1:10086/eureka/
server:port: 9090

创建一个OrderController类,提供/order/getOrder接口,该接口调用OrderService的getOrder()方法:

package com.example.controller;import com.example.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/order")
public class OrderController {@AutowiredOrderService orderService;@GetMapping("/getOrder")public String getOrder(){System.out.println("Come here to get Order....===");return orderService.getOrder();}}

创建一个OrderService类,增加@Service注解加入Spring容器:

package com.example.service;import com.example.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class OrderService {@Autowiredprivate RestTemplate restTemplate;public String getOrder(){//通过userService获取user信息String url="http://userservice/user/getUser";System.out.println("url"+url);User user=restTemplate.getForObject(url,User.class);System.out.println(user);return user.getName();}
}

OrderService类注入RestTemplate 对象,getOrder方法通过RestTemplate 对象调用userservice的/user/getuser接口获取User对象。之后返回获取到的user对象的name。

一切都是为了测试验证Eureka功能,所以不管是userService还是orderService,功能都非常简单。

orderservice还剩最后一步:启动类。

package com;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;@SpringBootApplication
@EnableEurekaClient
public class OrderServiceApplication {public static void main(String[] args) {SpringApplication.run(OrderServiceApplication.class);}@Bean@LoadBalancedpublic RestTemplate restTemplate(){return new RestTemplate();}}

增加@EnableEurekaClient注解(不过发现不加这个注解也不影响功能实现,等待后续解析源码学习底层原理的时候再研究这个注解的具体作用)。

启动类中通过@Bean的方式增加RestTemplate 对象的注入(注入到Spring IoC容器中),并且增加@LoadBanance注解,表明通过RestTemplate 对象调用userservice服务的时候需要实现负载均衡功能。

OK,所有的代码准备工作已完成。

测试

第一步,为了测试验证orderservice调用userservice的时候的负载均衡功能,需要启动多个userservice。

idea提供了这个能力,只不过需要在configuration中通过虚拟机参数指定服务端口:
在这里插入图片描述
我们一共配置了3个userservice。

orderService无所谓,其实有一个就够了。

我们顺序启动几个服务:

  1. eureka注册中心服务eureka-service(其实上面我们已经启动过了)。
  2. userservice服务userservice
  3. userservice服务userservice1
  4. userservice服务userservice2
  5. orderservice服务ordersercice

服务启动之后,在idea的service监控窗口可以看到各服务的启动端口、以及状态:
在这里插入图片描述

通过浏览器看一下eureka的工作状态:
在这里插入图片描述
可以看到当前注册到Eureka注册中心的共有4个服务,一个orderservice,3个userservice。

好了,可以开始测试了。

通过浏览器访问orderservice的getorder方法:
在这里插入图片描述
可以正常访问到orderservice服务的接口/order/getorder,并且,orderservice通过restTemplate、以及Eureka客户端可以正常访问到微服务userservice的/user/getuser接口!

说明Eureka注册中心的注册功能、已经Eureka客户端向注册中心拉取服务列表、访问其服务列表中的服务等功能已经可以正常工作了。

通过浏览器反复刷新localhost:9090/order/getOrder接口,多次访问,之后在idea的运行窗口观察userservice的log:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
发现8080端口的、8081端口的、以及8082端口的userservice服务会被轮番调用,说明loadbalance功能也已经可以正常工作了。

至于负载均衡策略,留待以后研究吧。

当然我们可以shutdown掉一个userservice,可以发现前端访问/order/getorder接口不受影响,也简单说明了通过Spring Cloud微服务功能可以提高系统服务能力、增强可靠性和可访问能力。

但是,需要补充一下,down掉一个userservice之后,前端访问/order/getorder接口偶然会出现失败的情况,说明一个问题:userservice服务down掉之后,并没有立即反馈给Eureka注册中心(因为有心跳周期的问题),之后,同步给Eureka注册中心之后,orderservice的本地服务列表也应该是需要时间来更新的,所以userservice服务down掉一段时间之后,前端访问才能正常。

let’s say it’s a day!

上一篇 SpringBoot 自动配置@EnableAutoConfiguration

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/127500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

11.2树的高度,表达式树,非递归遍历,层序遍历,奇偶树

课上 前序&#xff0c;根左右 中序&#xff0c;左根右 若前序中序相同&#xff0c;则树都没有左节点 求树的高度 表达式树 中缀表达式树 主要考虑括号问题 这个就是考虑递归底层&#xff0c;要结束时的情形&#xff1b;以及根节点的情形&#xff1b; 由于表达式树是满树&…

使用稳定扩散和SAM修改图像内容

推荐稳定扩散AI自动纹理工具&#xff1a; DreamTexture.js自动纹理化开发包 介绍 大型语言模型 &#xff08;LLM&#xff09; 和基础计算机视觉模型的最新突破为编辑图像或视频解锁了新的界面和方法。您可能听说过修复、复绘、生成填充和文本到图像;这篇文章将向您展示如何通过…

【git】git拉取代码报错,fatal: refusing to merge unrelated histories问题解决

大家好&#xff0c;我是好学的小师弟。今天准备将之前写的代码&#xff0c;拉到新的工程文件夹(仓库)下面&#xff0c;用了pull命令&#xff0c;结果报错了&#xff0c;报错截图如下 $ git pull https://gitee.com/* #仓库地址 fatal: refusing to merge unrelated histor…

JavaEE-cookie和session

本部分内容包括 cookie基本概念&#xff0c;sendcookies和getcookies代码&#xff1b; session基本概念&#xff0c;session实现登陆界面&#xff1b; 上述过程中涉及的代码如下&#xff1a; 1 import javax.servlet.ServletException; import javax.servlet.annotation.WebSe…

java实现pdf文件添加水印,下载到浏览器

java实现pdf文件添加水印&#xff0c;下载到浏览器 添加itextpdf依赖 <dependency><groupId>com.itextpdf</groupId><artifactId>itextpdf</artifactId><version>5.5.8</version> </dependency>文件下载到浏览器和指定路径 …

Java-数组的定义与使用

本章重点&#xff1a; 1. 理解数组基本概念 2. 掌握数组的基本用法 3. 数组与方法互操作 4. 熟练掌握数组相关的常见问题和代码 1. 数组的基本概念 1.1 为什么要使用数组 public class TestStudent{public static void main(String[] args){int score1 70;int s…

有色金属冶炼VR虚拟场景互动教学有何优势

真实模拟&#xff1a;VR虚拟现实技术可以提供一个真实的虚拟环境&#xff0c;模拟钢铁制造现场&#xff0c;包括设备、工艺流程、操作规程等&#xff0c;使学员获得直观、真实的体验。 安全可靠&#xff1a;钢铁制造技能培训可以在虚拟环境中进行&#xff0c;不会对人员或设备造…

Java架构师知识产权与标准化

目录 1 导学2 知识产权概述3 保护期限4 知识产权人的确定4 侵权判断5 标准划分想学习架构师构建流程请跳转:Java架构师系统架构设计 1 导学 2 知识产权概述 知识产权是指公民、法人、非法人单位对自己的创造性智力成果和其他科技成果依法享有的民事权。是智力成果的创造人依…

JVM虚拟机:堆结构的逻辑分区

堆内存的逻辑分区 堆内存的逻辑分区如下所示: 堆内存中分为新生代和老年代,二者空间大小1:3。在新生代里面分为两类区域(eden、survivor),三个区域(eden、survivor、survivor),三个区大小比例为8:1:1。 对象存放的位置 栈 当我们new一个对象的时候,首先会将对象…

Jorani远程命令执行漏洞 CVE-2023-26469

Jorani远程命令执行漏洞 CVE-2023-26469 漏洞描述漏洞影响漏洞危害网络测绘Fofa: title"Jorani"Hunter: web.title"Jorani" 漏洞复现1. 获取cookie2. 构造poc3. 执行命令 漏洞描述 Jorani是一款开源的员工考勤和休假管理系统&#xff0c;适用于中小型企业…

如何提高滚柱导轨的精度?

滚柱导轨是一种高精度的传动零部件&#xff0c;起导向作用&#xff0c;如果滚柱导轨的精度受损&#xff0c;则无法达到预期的使用效果&#xff0c;那么&#xff0c;我们应该如何提高滚柱导轨的精度呢&#xff1f; 1、优化材料选型&#xff1a;选用高质量的材料作为制造导轨的原…

Jetpack:026-Jetpack中的Slider

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了Jetpack多点触控相关的内容&#xff0c;本章回中 主要介绍Slider。闲话休提&#xff0c;让我们一起Talk Android Jetpack吧&#xff01; 1. 概念介绍 我们在本章回…

UEditorPlus v3.6.0 图标补全,精简代码,快捷操作重构,问题修复

UEditor是由百度开发的所见即所得的开源富文本编辑器&#xff0c;基于MIT开源协议&#xff0c;该富文本编辑器帮助不少网站开发者解决富文本编辑器的难点。 UEditorPlus 是有 ModStart 团队基于 UEditor 二次开发的富文本编辑器&#xff0c;主要做了样式的定制&#xff0c;更符…

AI技术发展:防范AI诈骗,守护数字安全

随着AI技术的迅猛发展&#xff0c;人工智能赋予了计算机更多的能力&#xff0c;包括自然语言处理、图像生成、声音合成等。这些领域的突破为人们提供了全新的体验和便捷&#xff0c;但同时也催生了一些潜在的安全风险&#xff0c;其中最突出的就是AI诈骗。本文将探讨如何防范AI…

竖版视频怎么做二维码?扫码播放竖版视频的方法

当我们在将视频转二维码图片展示的时候&#xff0c;一般横版视频在手机展示不会有影响&#xff0c;但是竖版视频会默认用横版的方式播放就会导致无法清晰的看到画面的内容&#xff0c;那么如何将竖版视频生成二维码是很多小伙伴头疼的一个问题。那么下面教大家使用二维码生成器…

Java程序员面试核心知识--Java基础知识(一)

目录 一、Java程序初始化顺序 二、Java的Clone方法作用 三、 OverLoad&#xff08;重载&#xff09;与Override&#xff08;重写&#xff09;区别 四、abstract class&#xff08;抽象类&#xff09;与interface&#xff08;接口&#xff09;的异同 五、String、StringBuf…

3D RPG Course | Core 学习日记三:Navigation智能导航地图烘焙

前言 前面我们已经绘制好了一个简单的地图场景&#xff0c;现在我们需要使用Navigation给地图做智能导航&#xff0c;以实现AI自动寻路&#xff0c;以及设置地图的可行走区域以及不可行走区域&#xff0c;Navigation的基础知识、原理、用法在Unity的官方文档&#xff0c;以及网…

【23真题】难!均79分!211题目强过985!

今天分享的是23年海南大学838的信号与系统试题及解析。 本套试卷难度分析&#xff1a;22年海南大学838考研真题&#xff0c;我也做过&#xff0c;若有需要戳这里自取&#xff01;平均分为80-90左右&#xff0c;最高分为133分。本套试题难度中等偏上&#xff0c;题量不多&#…

瓦斯抽采VR应急救援模拟仿真系统筑牢企业安全生产防线

矿工素质对安全生产的影响很大。传统的煤矿安全事故培训出于条件差、经验少加上侥幸心理&#xff0c;导致其在教学内容时过于简单且不切合实际&#xff0c;无法真正发挥培训作用。瓦斯检查作业VR模拟实操培训通过真实还原煤矿作业环境&#xff0c;让受训者身临其境地进入三维仿…

chatgpt接口调用

在线接口文档&#xff1a; https://app.apifox.com/invite?tokensymrLP7sojF6N31kZqnpZ 接口地址 https://chat.xutongbao.top/api/light/chat/createChatCompletion 请求方式 POST 请求参数 token String, 必须 prompt Array, 必须 例子一&#xff1a; 包含上下文 [ { "…