微服务springcloud 04. 远程调用,负载平衡,重试,ribbon框架

news2024/11/24 19:59:35

01.springcloud中关于远程调用,负载平衡。
在这里插入图片描述
在这里插入图片描述

02.远程调用
ribbon 提供了负载均衡和重试功能, 它底层是使用 RestTemplate 进行 Rest api 调用RestTemplate,RestTemplate 是SpringBoot提供的一个Rest远程调用工具。
它的常用方法:
getForObject() - 执行get请求
postForObject() - 执行post请求
第一步:创建springboot项目,新建 ribbon 项目
在这里插入图片描述

添加web和eureka discovery client依赖
在这里插入图片描述
第二步:添加通用commons
eureka-client 中已经包含 ribbon 依赖
需要添加 sp01-commons 依赖

<?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.3.1.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>cn.tedu</groupId>
	<artifactId>sp06-ribbon</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>sp06-ribbon</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<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-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>cn.tedu</groupId>
			<artifactId>sp01-commons</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<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>

第三步:修改spring.application的name属性,其他不改
application.yml文件中:

spring:
  application:
    name: ribbon

server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

第四步:主程序修改

package cn.tedu.sp06;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {

	public static void main(String[] args) {
		SpringApplication.run(Sp06RibbonApplication.class, args);
	}

	//创建RestTemplate实例,并存入spring容器中
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}
}

创建 RestTemplate 实例
RestTemplate 是用来调用其他微服务的工具类,封装了远程调用代码,提供了一组用于远程调用的模板方法,例如:getForObject()、postForObject() 等
第五步:创建RibbonController,实现远程调用

package cn.tedu.sp06.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.web.util.JsonResult;

@RestController
public class RibbonController {
	@Autowired
	private RestTemplate rt;

	@GetMapping("/item-service/{orderId}")
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
		//向指定微服务地址发送 get 请求,并获得该服务的返回结果 
		//{1} 占位符,用 orderId 填充
		return rt.getForObject("http://localhost:8001/{1}", JsonResult.class, orderId);
	}

	@PostMapping("/item-service/decreaseNumber")
	public JsonResult decreaseNumber(@RequestBody List<Item> items) {
		//发送 post 请求
		return rt.postForObject("http://localhost:8001/decreaseNumber", items, JsonResult.class);
	}


	@GetMapping("/user-service/{userId}")
	public JsonResult<User> getUser(@PathVariable Integer userId) {
		return rt.getForObject("http://localhost:8101/{1}", JsonResult.class, userId);
	}

	@GetMapping("/user-service/{userId}/score") 
	public JsonResult addScore(
			@PathVariable Integer userId, Integer score) {
		return rt.getForObject("http://localhost:8101/{1}/score?score={2}", JsonResult.class, userId, score);
	}


	@GetMapping("/order-service/{orderId}")
	public JsonResult<Order> getOrder(@PathVariable String orderId) {
		return rt.getForObject("http://localhost:8201/{1}", JsonResult.class, orderId);
	}

	@GetMapping("/order-service")
	public JsonResult addOrder() {
		return rt.getForObject("http://localhost:8201/", JsonResult.class);
	}
}

第六步:启动服务,并访问测试

03.负载平衡
在ribboncontroller中,url的域名都是写到固定。localhost:8001等。这就会一直访问一个service服务,不会做到访问其他相同的service服务。
修改 sp06-ribbon 项目,做到负载平衡,也就是url中不写固定的localhost
在这里插入图片描述
1.添加 ribbon 起步依赖(可选)
eureka 依赖中已经包含了 ribbon

<dependency>
	  <groupId>org.springframework.cloud</groupId>
	  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

2.RestTemplate 设置 @LoadBalanced
@LoadBalanced 负载均衡注解,会对 RestTemplate 实例进行封装,创建动态代理对象,并切入(AOP)负载均衡代码,把请求分发到集群中的服务器


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {

	public static void main(String[] args) {
		SpringApplication.run(Sp06RibbonApplication.class, args);
	}

	//创建RestTemplate实例,并存入spring容器中
	@LoadBalanced //负载均衡注解
	@Bean
	public RestTemplate getRestTemplate() {
		return new RestTemplate();
	}

3.访问路径设置为服务id(改localhost:8001 为 item-service)

package cn.tedu.sp06.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.web.util.JsonResult;

@RestController
public class RibbonController {
	@Autowired
	private RestTemplate rt;

	@GetMapping("/item-service/{orderId}")
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
		//向指定微服务地址发送 get 请求,并获得该服务的返回结果 
		//{1} 占位符,用 orderId 填充
		return rt.getForObject("http://item-service/{1}", JsonResult.class, orderId);
	}

	@PostMapping("/item-service/decreaseNumber")
	public JsonResult decreaseNumber(@RequestBody List<Item> items) {
		//发送 post 请求
		return rt.postForObject("http://item-service/decreaseNumber", items, JsonResult.class);
	}


	@GetMapping("/user-service/{userId}")
	public JsonResult<User> getUser(@PathVariable Integer userId) {
		return rt.getForObject("http://user-service/{1}", JsonResult.class, userId);
	}

	@GetMapping("/user-service/{userId}/score") 
	public JsonResult addScore(
			@PathVariable Integer userId, Integer score) {
		return rt.getForObject("http://user-service/{1}/score?score={2}", JsonResult.class, userId, score);
	}

	@GetMapping("/order-service/{orderId}")
	public JsonResult<Order> getOrder(@PathVariable String orderId) {
		return rt.getForObject("http://order-service/{1}", JsonResult.class, orderId);
	}

	@GetMapping("/order-service")
	public JsonResult addOrder() {
		return rt.getForObject("http://order-service/", JsonResult.class);
	}
}

4.访问测试
访问测试,ribbon 会把请求分发到 8001 和 8002 两个服务端口上
http://localhost:3001/item-service/34
在这里插入图片描述
在这里插入图片描述
ribbon 重试
在这里插入图片描述

01.pom.xml 添加 spring-retry 依赖

<dependency>
		<groupId>org.springframework.retry</groupId>
		<artifactId>spring-retry</artifactId>
</dependency>

02.application.yml 配置 ribbon 重试

spring:
  application:
    name: ribbon

server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
ribbon:
  MaxAutoRetriesNextServer: 2
  MaxAutoRetries: 1
  OkToRetryOnAllOperations: true

MaxAutoRetriesNextServer
请求失败后,更换服务器的次数
MaxAutoRetries
当前请求失败后重试次数,尝试失败会更换下一个服务器
OkToRetryOnAllOperations=true
默认只对GET请求重试, 当设置为true时, 对POST等所有类型请求都重试
03.主程序设置 RestTemplate 的请求工厂的超时属性

package cn.tedu.sp06;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class Sp06RibbonApplication {

	public static void main(String[] args) {
		SpringApplication.run(Sp06RibbonApplication.class, args);
	}

	//创建RestTemplate实例,并存入spring容器中
	@LoadBalanced //负载均衡注解
	@Bean
	public RestTemplate getRestTemplate() {
		SimpleClientHttpRequestFactory f = new SimpleClientHttpRequestFactory();
		f.setConnectTimeout(1000);
		f.setReadTimeout(1000);
		return new RestTemplate(f);
		//return new RestTemplate();
	}
}

有两个属性ConnectTimeout,ReadTimeout,这个两个属性不能在yml文件中去进行配置,而是需要在主启动类中进行配置。
其中,ConnectTimeout , java 是这样解释的。 意思是用来建立连接的时间。如果到了指定的时间,还没建立连接,则报异常。
ReadTimeout , java 是这样解释的。 意思是已经建立连接,并开始读取服务端资源。如果到了指定的时间,没有可能的数据被客户端读取,则报异常。
这两个都java中写好的,不是ribbon的属性,但是也是必须的
05.item-service 的 ItemController 添加延迟代码,以便测试 ribbon 的重试机制

package cn.tedu.sp02.item.controller;

import java.util.List;
import java.util.Random;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.service.ItemService;
import cn.tedu.web.util.JsonResult;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@RestController
public class ItemController {
	@Autowired
	private ItemService itemService;

	@Value("${server.port}")
	private int port;

	@GetMapping("/{orderId}")
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) throws Exception {
		log.info("server.port="+port+", orderId="+orderId);
		///--设置随机延迟
		if(Math.random()<0.6) { 
			long t = new Random().nextInt(5000);//5000以内的随机数
			log.info("item-service-"+port+" - 暂停 "+t);
			Thread.sleep(t);
		}
		List<Item> items = itemService.getItems(orderId);
		return JsonResult.ok(items).msg("port="+port);
	}

	@PostMapping("/decreaseNumber")
	public JsonResult decreaseNumber(@RequestBody List<Item> items) {
		itemService.decreaseNumbers(items);
		return JsonResult.ok();
	}
}

06.访问,测试 ribbon 重试机制
通过 ribbon 访问 item-service,当超时,ribbon 会重试请求集群中其他服务器
http://localhost:3001/item-service/35
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

「深度学习之优化算法」(六)遗传算法

1. 遗传算法简介 遗传算法(Genetic Algorithms&#xff0c;GA)是一种模拟自然中生物的遗传、进化以适应环境的智能算法。由于其算法流程简单&#xff0c;参数较少优化速度较快&#xff0c;效果较好&#xff0c;在图像处理、函数优化、信号处理、模式识别等领域有着广泛的应用。…

电气火灾探测器在智慧城市消防安全的应用 安科瑞 许敏

【摘要】智慧消防应用是重要的建设内容之一。根据固定资产投资额和消防经费测算&#xff0c;2017年消防市场容量合计约2761.65亿元&#xff0c;2020年消防市场规模可达5200亿元。通过梳理各地政府招标项目&#xff0c;预计全国政府智慧消防项目的投入总额可达92.8亿元。 【关键…

基于Java校园美食交流系统设计实现(源码+lw+部署文档+讲解等)

博主介绍&#xff1a; ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精…

crontab执行时间与系统时间不一致

crontab执行时间与系统时间不一致 一&#xff1a;问题查找&#xff1a; 问题描述&#xff1a;今天新发现一个问题&#xff0c;定时任务写了之后一直不执行&#xff0c;查看日志才发现&#xff0c;执行的时间给我定时的时间相差了12个小时。 1、查看定时任务的相关日志&#…

Nik Color Efex 滤镜详解(1/5)

双色滤镜 Bi-Color Filter 混合两种颜色然后将混合结果添加到图像&#xff0c;以此模拟传统的双色玻璃滤镜效果。 颜色组合 Color Set 提供棕色、冷/暖、绿色/棕色、青苔色、紫色/粉红色等多种颜色组合&#xff0c;每个颜色组合又有 4 种版本可供选择。 不透明度 Opacity 调整…

Stuart Russell对话姚期智:为全人类设计AI系统,可以借鉴墨子「兼爱」思想丨2023智源大会AI安全与对齐论坛...

导读 在2023智源大会「AI安全与对齐论坛」的对话环节&#xff0c;加州大学伯克利分校教授Stuart Russell与图灵奖得主、中国科学院院士姚期智针对「如何设计对人类有益的AI」、「如何管控AI技术」&#xff0c;以及「LLM内在目标与意识」等话题进行了深度探讨&#xff0c;其中St…

一键式 RLHF 训练 DeepSpeed Chat(二):实践篇

一键式 RLHF 训练 DeepSpeed Chat&#xff08;二&#xff09;&#xff1a;实践篇 之前给大家分享了一键式 RLHF 训练 DeepSpeed Chat&#xff08;一&#xff09;&#xff1a;理论篇&#xff0c;本文给大家分享如何使用DeepSpeed Chat进行RLHF训练。 DeepSpeed Chat 的 RLHF 训…

每日算法(第二十三期)

先来回顾一下上期的问题及答案&#xff1a; 2023年6月14日 「最接近的三数之和」&#xff08;3Sum Closest&#xff09;。以下是题目的描述&#xff1a; 给定一个包括 n 个整数的数组 nums 和一个目标值 target。找出 nums 中的三个整数&#xff0c;使得它们的和与 target 最接…

活动预告 | Hugging Face 音频 AI 派对直播

嘿嘿嘿&#xff0c;&#x1f917; 宝子们&#xff01;我们正在准备一个超级激动人心的音频 AI 派对&#xff0c;千万别错过&#xff01;为了庆祝 Hugging Face 新开设的免费开源 Audio Transformers 课程的启动&#xff0c;我们组织了一场不容错过的网络直播活动&#xff01; &…

Docker 容器入侵排查

随着越来越多的应用程序运行在容器里&#xff0c;各种容器安全事件也随之发生&#xff0c;例如攻击者可以通过容器应用获取容器控制权&#xff0c;利用失陷容器进行内网横向&#xff0c;并进一步逃逸到宿主机甚至攻击K8s集群。 容器的运行环境是相对独立而纯粹&#xff0c;当容…

redis客户端连接不上redis

总结 我先说一下&#xff0c;我觉得最有效就是把Linux防火墙tm的关了&#xff0c; 当我成功后&#xff0c;第二次连接时&#xff0c;防火墙开着&#xff0c;但是我能连接。 systemctl stop firewalled # 关闭防火墙 systemctl start firewalled # 开启防火墙 systemctl status …

利用DPU/IPU 卸载容器镜像以及文件系统的相关操作

1、背景和动机 随着云原生(Cloud Native)被工业界广泛接受&#xff0c;容器(container)在数据中心被广泛部署&#xff0c;其地位正在逐步取代传统的虚拟机(Virtual Machine)。当然目前依然存在用轻量虚拟机来运行和部署容器&#xff0c;比如使用Kata Containers。简单来讲&…

FPGA实现USB3.0 UVC 相机OV5640摄像头输出 基于FT602驱动 提供工程源码和QT上位机源码

目录 1、前言2、UVC简介3、FT602芯片解读4、我这儿的 FT601 USB3.0通信方案5、详细设计方案基于FT602的UVC模块详解 6、vivado工程详解7、上板调试验证8、福利&#xff1a;工程代码的获取 1、前言 目前USB3.0的实现方案很多&#xff0c;但就简单好用的角度而言&#xff0c;FT6…

2023 年 8 个最佳 React UI 组件库和框架

将展示八个最好的 React UI 组件库和框架&#xff0c;如下表所示&#xff1a;&#xff08;星标加关注&#xff0c;开车不迷路&#xff09; 「React Bootstrap&#xff1a;」一个与 Bootstrap 框架集成的实用的 React UI 库。「Grommet&#xff1a;」如果您想在设计中实现可访问…

基于Servlet+mysql+jsp学生宿舍信息管理系统

基于Servletmysqljsp学生宿舍信息管理系统 一、系统介绍二、功能展示1.用户登陆2.学生-主页面3.学生-缺勤记录4.学生-修改密码5.宿舍管理员-主页面6.宿舍管理员-学生查看7.宿舍管理员-缺勤记录8.系统管理员-宿舍管理员管理9.系统管理员-学生管理10.系统管理员-宿舍楼管理11.系统…

中高级前端面试秘籍,为你保驾护航金三银四

引言 各位大佬在评论中指出的种种问题小弟万分感谢。由于这一年来&#xff0c;出了不少变动&#xff0c;所以才一直耽搁&#xff0c;现已修复各位大佬指出的问题和建议。请大家放心食用&#xff01;感恩~&#x1f973; 当下&#xff0c;正面临着近几年来的最严重的互联网寒冬&a…

《文渊》期刊简介及投稿邮箱

《文渊》期刊简介及投稿邮箱 《文渊》是正规国家级连续型电子期刊&#xff0c;新闻出版广电总局可查&#xff0c;国家级教育核心刊物、中国核心期刊数据库收录期刊。 主管单位&#xff1a;中国出版传媒股份有限公司 主办单位&#xff1a;中国出版传媒股份有限公司 文渊&…

变量的线程安全分析

目录 变量的线程安全 常见线程安全类 变量的线程安全 成员变量和静态变量是否线程安全&#xff1f; 如果它们没有共享&#xff0c;则线程安全 如果它们被共享了&#xff0c;根据它们的状态是否能够改变&#xff0c;又分两种情况 如果只有读操作&#xff0c;则线程安全如果…

【30天熟悉Go语言】7 Go流程控制之分支结构if、switch

文章目录 一、前言二、if1、单分支Go语法规范&#xff1a; 2、双分支Go语法规范 3、多分支 三、switch1、基本语法2、语法规范1&#xff09;switch2&#xff09;case3&#xff09;default 四、总结 一、前言 Go系列文章&#xff1a; GO开篇&#xff1a;手握Java走进Golang的世界…

手机APP大用户并发测试

一、背景 随着智能手机近年来的快速增长&#xff0c;从游戏娱乐到移动办公的各式各样的手机APP软件渗透到我们的生活中&#xff0c;对于大型的手机APP测试不仅要关注它的功能性、易用性还要关注它的性能&#xff0c;最近发现LoadRunner12可以对手机APP做性能测试&#xff0c;但…