微服务springcloud 06.feign框架,配合ribbon 负载均衡和重试,配合hystrix 降级,监控和熔断测试

news2024/12/26 0:08:40

feign是ribbon +hystrix 的整合
01.新建 sp09-feign 项目
第一步:
在这里插入图片描述
第二步:选择依赖:
在这里插入图片描述
pom.xml
需要添加 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>sp09-feign</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>sp09-feign</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-actuator</artifactId>
		</dependency>
		<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.cloud</groupId>
			<artifactId>spring-cloud-starter-openfeign</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>

第三步:修改sp09-feign项目的application.yml

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

第四步:sp09-feign的主程序添加 @EnableDiscoveryClient 和 @EnableFeignClients

package cn.tedu.sp09;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class Sp09FeignApplication {

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

}

02.feign 声明式客户端

feign 利用了我们熟悉的 spring mvc 注解来对接口方法进行设置,降低了我们的学习成本。
通过这些设置,feign可以拼接后台服务的访问路径和提交的参数

例如:

@GetMapping("/{userId}/score") 
JsonResult addScore(@PathVariable Integer userId, @RequestParam Integer score);

当这样调用该方法:

service.addScore(7, 100);

那么 feign 会向服务器发送请求:

http://用户微服务/7/score?score=100

注意:如果 score 参数名与变量名不同,需要添加参数名设置:
@GetMapping("/{userId}/score") 
JsonResult addScore(@PathVariable Integer userId, @RequestParam("score") Integer s);

第一步:声明三个代理接口

在这里插入图片描述
这里的三个Feign类型service接口,就好像是ribbon中的ribbonController(但是没有注解controller,并不能接受客户端的request请求,所以只是类似),只是调用service中的方法。具体方法的实现还是要在原来的service中去完成。
@FeignClient(“item-service”),中的item-service是在service服务中的application.yml文件中的spring.application.name来确定的

ItemFeignService:

package cn.tedu.sp09.service;

import java.util.List;

import org.springframework.cloud.openfeign.FeignClient;
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 cn.tedu.sp01.pojo.Item;
import cn.tedu.web.util.JsonResult;

@FeignClient("item-service")
public interface ItemFeignService {
	@GetMapping("/{orderId}")
	JsonResult<List<Item>> getItems(@PathVariable String orderId);

	@PostMapping("/decreaseNumber")
	JsonResult decreaseNumber(@RequestBody List<Item> items);
}

UserFeignService
注意,如果请求参数名与方法参数名不同,@RequestParam不能省略,并且要指定请求参数名:
@RequestParam(“score”) Integer s

package cn.tedu.sp09.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;

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

@FeignClient("user-service")
public interface UserFeignService {
	@GetMapping("/{userId}")
	JsonResult<User> getUser(@PathVariable Integer userId);

    // 拼接路径 /{userId}/score?score=新增积分
	@GetMapping("/{userId}/score") 
	JsonResult addScore(@PathVariable Integer userId, @RequestParam Integer score);
}

OrderFeignService:

package cn.tedu.sp09.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

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

@FeignClient("order-service")
public interface OrderFeignService {
	@GetMapping("/{orderId}")
	JsonResult<Order> getOrder(@PathVariable String orderId);

	@GetMapping("/")
	JsonResult addOrder();

}

第二步:编写FeignController,这个是用来接受web请求的,是真正的controller
FeignController:

package cn.tedu.sp09.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 cn.tedu.sp01.pojo.Item;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.sp01.pojo.User;
import cn.tedu.sp09.service.ItemFeignService;
import cn.tedu.sp09.service.OrderFeignService;
import cn.tedu.sp09.service.UserFeignService;
import cn.tedu.web.util.JsonResult;

@RestController
public class FeignController {
	@Autowired
	private ItemFeignService itemService;
	@Autowired
	private UserFeignService userService;
	@Autowired
	private OrderFeignService orderService;
	
	@GetMapping("/item-service/{orderId}")
	public JsonResult<List<Item>> getItems(@PathVariable String orderId) {
		return itemService.getItems(orderId);
	}

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

	
	@GetMapping("/user-service/{userId}")
	public JsonResult<User> getUser(@PathVariable Integer userId) {
		return userService.getUser(userId);
	}

	@GetMapping("/user-service/{userId}/score") 
	public JsonResult addScore(@PathVariable Integer userId, Integer score) {
		return userService.addScore(userId, score);
	}
	
	
	@GetMapping("/order-service/{orderId}")
	public JsonResult<Order> getOrder(@PathVariable String orderId) {
		return orderService.getOrder(orderId);
	}

	@GetMapping("/order-service")
	public JsonResult addOrder() {
		return orderService.addOrder();
	}
}

为什么可以直接在@GetMapping(“/order-service”)中直接写order-service,因为feign有ribbon技术,可以直接调用服务的服务名
调用流程
在这里插入图片描述
第三步:启动服务,并访问测试
在这里插入图片描述
http://eureka1:2001
http://localhost:3001/item-service/35

http://localhost:3001/item-service/decreaseNumber
使用postman,POST发送以下格式数据:
[{“id”:1, “name”:“abc”, “number”:23},{“id”:2, “name”:“def”, “number”:11}]

http://localhost:3001/user-service/7

http://localhost:3001/user-service/7/score?score=100

http://localhost:3001/order-service/123abc

http://localhost:3001/order-service/

03.配合ribbon 负载均衡和重试
无需额外配置,feign 默认已启用了 ribbon 负载均衡和重试机制。可以通过配置对参数进行调整

重试的默认配置参数:
ConnectTimeout=1000
ReadTimeout=1000
MaxAutoRetries=0
MaxAutoRetriesNextServer=1

第一步:可以在sp09-feign 项目的application.yml 配置 ribbon 超时和重试
ribbon.xxx 全局配置
item-service.ribbon.xxx 对特定服务实例的配置

spring:
  application:
    name: feign
    
server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
ribbon:
  ConnectTimeout: 1000
  ReadTimeOut: 1000
  MaxAutoRetries: 1
  MaxAutoRetriesNextServer: 2
item-service:
  ribbon:
    ConnectTimeout: 1000
    ReadTimeOut: 1000
    MaxAutoRetries: 2
    MaxAutoRetriesNextServer: 1

启动服务,访问测试
http://localhost:3001/item-service/35

04.feign + hystrix 降级
feign 启用 hystrix
第一步:feign 默认没有启用 hystrix,添加配置,启用 hystrix
feign.hystrix.enabled=true
application.yml 添加配置

feign:
  hystrix:
    enabled: true

第二步:降级类
降级类需要实现远程接口
ItemFeignServiceFB

package cn.tedu.sp09.service;

import java.util.List;
import org.springframework.stereotype.Component;
import cn.tedu.sp01.pojo.Item;
import cn.tedu.web.util.JsonResult;

@Component
public class ItemFeignServiceFB implements ItemFeignService{

	@Override
	public JsonResult<List<Item>> getItems(String orderId) {
		return JsonResult.err("获取订单失败");
	}

	@Override
	public JsonResult decreaseNumber(List<Item> items) {
		return JsonResult.err("减少库存失败");
	}
}

UserFeginServiceFB

package cn.tedu.sp09.service;

import org.springframework.stereotype.Component;
import cn.tedu.sp01.pojo.User;
import cn.tedu.web.util.JsonResult;

@Component
public class UserFeignServiceFB implements UserFeignService {

	@Override
	public JsonResult<User> getUser(Integer userId) {
		return JsonResult.err("获取用户失败");
	}

	@Override
	public JsonResult addScore(Integer userId, Integer score) {
		return JsonResult.err("增加积分失败");
	}

}

OrderFeignServiceFB

package cn.tedu.sp09.service;

import org.springframework.stereotype.Component;
import cn.tedu.sp01.pojo.Order;
import cn.tedu.web.util.JsonResult;

@Component
public class OrderFeignServiceFB implements OrderFeignService {

	@Override
	public JsonResult<Order> getOrder(String orderId) {
		return JsonResult.err("获取订单失败");
	}

	@Override
	public JsonResult addOrder() {
		return JsonResult.err("保存订单失败");
	}

}

第三步:在代理接口(ItemFeignService)中去声明降级类
远程调用失败, 会执行降级类中的代码,在注解@FeignClient中去添加属性fallback
ItemFeignService

@FeignClient(name="item-service",fallback = ItemFeignServiceFB.class)
public interface ItemFeignService {

UserFeignService

@FeignClient(name="user-service",fallback = UserFeignServiceFB.class)
public interface UserFeignService {

OrderFeignService

@FeignClient(name="order-service",fallback = OrderFeignServiceFB.class)
public interface OrderFeignService {

04.feign + hystrix 监控和熔断测试
在这里插入图片描述第一步:修改sp09-feign项目
pom.xml 添加 hystrix 起步依赖,feign 没有包含完整的 hystrix 依赖
右键点击项目,编辑起步依赖,添加hystrix依赖
在这里插入图片描述

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

第二步:主程序添加 @EnableCircuitBreaker

package cn.tedu.sp09;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

//@EnableCircuitBreaker
//@EnableDiscoveryClient
//@SpringBootApplication
@SpringCloudApplication
@EnableFeignClients
public class Sp09FeignApplication {

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

}

第三步:sp09-feign 配置 actuator,暴露 hystrix.stream 监控端点
actuator 依赖
查看pom.xml, 确认已经添加了 actuator 依赖

<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.yml 暴露 hystrix.stream 端点

management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

第四步:启动服务,查看监控端点
http://localhost:3001/actuator
在这里插入图片描述
第五步:启动hystrix dashboard
启动 hystrix dashboard 服务,填入feign监控路径,开启监控
访问 http://localhost:4001/hystrix

在其中填入 feign 监控路径:
http://localhost:3001/actuator/hystrix.stream

访问微服务,以产生监控数据

http://localhost:3001/item-service/35

http://localhost:3001/user-service/7
http://localhost:3001/user-service/7/score?score=100

http://localhost:3001/order-service/123abc
http://localhost:3001/order-service/
在这里插入图片描述
第六步:熔断测试
用ab工具,以并发50次,来发送20000个请求


ab -n 20000 -c 50 http://localhost:3001/item-service/35

断路器状态为 Open,所有请求会被短路,直接降级执行fallback方法
在这里插入图片描述

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

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

相关文章

游泳可以戴的耳机有哪些?四款专业的游泳耳机推荐

现在人们都开始热衷于运动健身&#xff0c;运动时大多会听音乐&#xff0c;市面上的运动耳机层出不穷&#xff0c;多数都是蓝牙耳机&#xff0c;但是有一些运动不太适合。 例如游泳&#xff0c;其他运动都可以将手机放在附近&#xff0c;但是游泳就不行了。所以游泳时可以听歌的…

【云服务】阿里云服务器镜像备份到本地

​ 首先&#xff0c;让我们了解一下阿里云平台上自定义镜像的功能。通过自定义镜像&#xff0c;用户可以将云服务器的当前状态保存为镜像&#xff0c;以便在需要时快速恢复到该状态。此外&#xff0c;自定义镜像还可以作为模板创建新的云服务器&#xff0c;方便用户快速部署相同…

1742_C语言中的指针与数组

全部学习汇总&#xff1a; GreyZhang/c_basic: little bits of c. (github.com) 之所以常常把数组与指针联系到一块儿是因为数组的名字在很多时候等同于指向数组首元素的指针。在写程序的时候&#xff0c;这常常会给我们带来很多方便。尤其是需要把数组作为一个函数的处理对象时…

Java并发(十一)----线程五种状态与六种状态

1、五种状态 这是从 操作系统 层面来描述的 【初始状态】仅是在语言层面创建了线程对象&#xff0c;还未与操作系统线程关联 【可运行状态】&#xff08;就绪状态&#xff09;指该线程已经被创建&#xff08;与操作系统线程关联&#xff09;&#xff0c;可以由 CPU 调度执行 …

Android Studio实现贪吃蛇小游戏

项目目录 一、项目概述二、开发环境三、详细设计四、运行演示五、项目总结 一、项目概述 贪吃蛇是一款经典的街机游戏&#xff0c;不仅在电子游戏史上占有一席之地&#xff0c;也在很多人的童年回忆中留下了深刻的印象。在游戏中&#xff0c;玩家需要操纵一条蛇通过吃食物来增…

leetcode222. 完全二叉树的节点个数(java)

完全二叉树的节点个数 leetcode222. 完全二叉树的节点个数题目描述 递归广度优先遍历二叉树专题 leetcode222. 完全二叉树的节点个数 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/count-complete-tree-nodes 题目描述…

Linux下的打包和压缩/解压解包

文章目录 一、打包和压缩二、Linux下进行打包和压缩1.zip指令&#xff0c;unzip指令2.tar指令 一、打包和压缩 打包呢就是把所有东西装在一起&#xff0c;然后压缩就是将这一包东西给它合理摆放&#xff0c;腾出更多的空间&#xff0c;以便放更多的东西。 压缩可以将如果东西是…

【github加载不出来】github 加载不出来、获取GitHub官方CDN地址、修改系统Hosts文件 刷新缓存

目录 github 加载不出来获取GitHub官方CDN地址修改系统Hosts文件刷新缓存 github 加载不出来 获取GitHub官方CDN地址 https://www.ipaddress.com/打开后如图&#xff0c;右上角搜索查 查找这三个DNS链接的解析地址 http://github.com http://assets-cdn.github.com http://git…

java springboot整合Druid数据源配置

整合的最后一块 我们整合一个数据源 Druid 我们还是打开idea 创建一个项目 路径和版本调一下 路径选一个好的目录就可以了 至于版本 最好是 java 8 JDK 1.8 然后 Next 下一步 这里 spring boot 的版本记得选一下 不要搞太高 2.几即可 Druid 在这里 显然也是找不到的 所以 我…

安卓端Google隐私沙盒归因报告聚焦

自2022年2月Google首次提出将推出隐私沙盒至今已一年有余。现在&#xff0c;安卓端的隐私沙盒Beta测试已针对特定Android13设备正式开始。作为早期测试者&#xff0c;Adjust很高兴与 Google一同迈出增强用户隐私的第一步&#xff0c;并在接下来的旅程中继续携手同行。为帮助移动…

framework编译应用代码

代码编译 APP或Service代码单编调试 1、在aosp文件目录下在将环境变量加载到内存中&#xff0c;在终端中输入下面命令 source build/envsetup.sh 2、选择平台编译选项 lunch 3、输入后会出现一个选择列表&#xff0c;然后输入你想要的项目的序号即可。如下所示我这里选择的7…

【OpenMMLab AI实战营二期笔记】第十天 底层视觉与MMEditing

1.图像超分辨率 1.1 什么是图像超分辨率&#xff1f; 根据从低分辨率图像重构高分辨率图像 1.2 目标&#xff1a; 提高图像的分辨率高分图像符合低分图像的内容恢复图像的细节、产生真实的内容 1.3 应用&#xff1a; 经典游戏高清重制动画高清重制照片修复节约传输高清图…

当你拥有什么样的高性能计算技术水平,你才能成为一名高性能计算工程师? ...

在当今科技快速发展的时代&#xff0c;高性能计算工程师成为了推动科学研究、工程仿真和大数据处理的关键人才。尤其是我国大力发展科研基建&#xff0c;打造科研技术底座&#xff0c;这就更加需要高性能计算工程师通过自身的技术来加速科研建设和研发的进度和速度。 我们调研了…

Spark大数据处理学习笔记(3.8.1) Spark RDD典型案例-利用RDD计算总分与平均分

该文章主要为完成实训任务&#xff0c;详细实现过程及结果见【http://t.csdn.cn/Twpwe】 文章目录 1. 任务目标2. 实现思路3. 准备工作3.1 启动HDFS服务3.2 启动Spark服务3.3 在本地创建成绩文件3.4 将成绩文件上传到HDFS 4. 完成任务4.1 在Spark Shell里完成任务4.1.1 读取成绩…

虚拟机使用

文章目录 VMWare安装Warning 系统安装MacOS解锁工具Unlocker Warning VMWare配置系统启动安装VMware tools联网 VMWare安装 Warning 安装完VMWare后要在BIOS中开启intel VT&#xff08;虚拟化&#xff09;&#xff0c;否则安装过程中会出错&#xff0c;提示“Intel VT-x处于禁…

写在2023年,回看10年前,很幸运进了软件测试这行~

首先介绍一下我自己&#xff0c;从事软件测试行业到现在是10年时间&#xff0c;毕业之后一直从事的软件测试行业。很幸运在毕业时赶上互联网这波浪潮&#xff0c;然后就一直在互联网公司工作&#xff0c;虽然那时候的软件测试技术发展还相对比较混乱&#xff0c;但自己因为公司…

CAN 报文字节排列顺序(Intel、Motorola_LSB、Motorola_MSB)

学习自记&#xff1a; 在定义CAN通信矩阵或制作dbc时&#xff0c;我们需要知道报文的字节排列顺序。字节的排列顺序有2种&#xff0c;一种是Intel的排列顺序&#xff0c;另一种是Motorola的排列顺序&#xff0c;就跟大小端字节排序是一样的。下面笔者将简单介绍这2种字节排序的…

在conda环境中安装tensorflow和cuda

​ 不同版本的tensorflow官方提供的编译好的whl文件只对应一个cuda版本&#xff0c;这让需要tensorflow的不同版本时很麻烦。 我选择的方式是在conda中新建一个环境&#xff0c;在环境中安装需要的tensorflow和cudatoolkit。 这里假设已经安装好anaconda。 确定需要的tensorflo…

服了呀,现在的00后,真的是卷死了,辞职信已经写好准备提交了·····

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该卷的还是卷。这不&#xff0c;四月份春招我们公司来了个00后&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪22K&#xff0c;都快接近我了。 后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了…

数智赋能与低代码:是医药行业的创新引擎还是心魔歧途

医药行业在当下科技水平的推动下实现了突破性的进展&#xff0c;提高了疾病的治疗效果、加速了新药的开发速度&#xff0c;并为病患提供了更便捷、个性化的医疗服务。当前科技水平下的医药行业正在经历快速的发展和创新。AI 在医药研发、诊断和治疗方面扮演着重要角色。机器学习…