服务调用---------Ribbon和Feign

news2024/9/21 18:31:17

1、Ribbon

1.1 Ribbon简介

Ribbon是一个用于客户端负载均衡的组件,它是Netflix开源的一个项目。在微服务架构中,系统会拆分为多个小型的服务,每个服务都有自己独立的服务器实例。Ribbon所具有的特点:客户端负载均衡,将请求发送到多个服务实例中的一个。多种负载均衡算法:Ribbon支持多种负载均衡算法,如轮询、随机、权重等,可以根据应用的需求选择适合的算法。服务实例自动发现:Ribbon可以与服务注册中心集成,自动发现可用的服务实例。容错和重试机制:如果某个服务实例不可用,Ribbon会自动选择另一个可用的实例进行请求,提高系统的容错能力。

1.2 Ribbon负载均衡

负载均衡原理

服务提供者order-service通过发起请求localhost:8080/order/101远程调用http://user-service/user/1分别轮询转发到服务消费者user-service和user-service1。

//继承客户端请求的负载均衡拦截器
LoadBalancerInterceptor implements ClientHttpRequestInterceptor

@Override
	public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
			final ClientHttpRequestExecution execution) throws IOException {
		final URI originalUri = request.getURI();  //服务的路径
		String serviceName = originalUri.getHost();  // 不同路径的服务名
		Assert.state(serviceName != null,
				"Request URI does not contain a valid hostname: " + originalUri);
		return this.loadBalancer.execute(serviceName,   // 处理不同服务执行路径
				this.requestFactory.createRequest(request, body, execution));
	}

//从服务列表中选择一个去执行
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)
			throws IOException {
		ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
		Server server = getServer(loadBalancer, hint);
		if (server == null) {
			throw new IllegalStateException("No instances available for " + serviceId);
		}
		RibbonServer ribbonServer = new RibbonServer(serviceId, server,
				isSecure(server, serviceId),
				serverIntrospector(serviceId).getMetadata(server));

		return execute(serviceId, ribbonServer, request);
	}

负载均衡策略

实现类

名称

解释

RoundRobinRule

轮询策略

按照轮询的方式选择可用的服务实例,依次轮流分发请求。

RandomRule

随机策略

随机选择可用的服务实例来处理请求。

WeightedResponseTimeRule

加权响应时间策略

根据每个服务实例的响应时间和权重,来计算一个权重值,选择权重值较小的实例处理请求。

RetryRule

重试策略

在选择可用的服务实例时,会在一定次数内进行重试,以提高容错能力。

BestAvailableRule

最低并发策略

会先过滤出并发连接数量最低的服务实例,然后从中选择一个处理请求。

AvailabilityFilteringRule

可用性过滤策略

首先排除因故障而被标记为不可用的服务实例,然后按照轮询的方式选择可用的服务实例。

ZoneAvoidanceRule

区域感知策略

Ribbon会根据服务实例所在的区域以及区域的可用性来选择服务实例。

Ribbon和Nginx的区别

架构上:Ribbon是一个客户端负载均衡组件,它通常与服务调用客户端集成在一起,通过轮询、随机等算法选择可用的服务实例。而Nginx是一个独立的反向代理服务器,用于将客户端请求转发给后端服务器。

协议上:Ribbon主要用于HTTP、TCP等通信协议的负载均衡,适用于微服务架构中的服务调用。而Nginx支持更多的协议,如HTTP、HTTPS、SMTP、POP3等,可以用于多场景的负载均衡和反向代理。

功能上:Ribbon提供了更灵活的负载均衡策略、重试机制、服务健康检查等功能,且可以与Spring Cloud等技术栈集成,方便在微服务架构中使用。而Nginx不仅具有负载均衡和反向代理的功能,还支持缓存、gzip压缩、SSL/TLS加密等高级特性。

部署管理上:Ribbon通常作为客户端的一部分集成在应用程序中,可以在应用中灵活配置和管理,适合分布式部署。而Nginx是独立的服务器软件,需要单独部署和配置,可以集中管理多个应用的负载均衡配置。

1.3 服务调用和Ribbon负载均衡实现

Ribbon依赖于spring-cloud-starter-netflix-eureka-client包

  •  自定义创建远程调用对象
/**
     * 远程调用和负载均衡
     * @return
     */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

controller发出的请求完成调用并进行负载均衡默认的轮询负载均衡

//远程调用
User user = restTemplate.getForObject("http://user-service/user/" + order.getUserId(), User.class);

自定义负载均衡策略对象

/**
     * 自定义负载均衡策略
     */
    @Bean
    public IRule randomRule(){
        return new RandomRule();
    }

application.yml配置负载均衡策略

user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
ribbon:
  eager-load:
    enabled: true
    clients: userservice  # 饥饿加载

以上是Ribbon完成的负载均衡调用远程微服务。

2、Feign&openFeign

Feign是一个受Retrofit、JAXRS-2.0和WebSocket启发的Java到HTTP客户端绑定。是声明式客户端,通过发送Rest接口进行请求。为了维护请求参数,让编程规范更统一使代码更有可读性。

官网

  • pom.xml
<!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
  • 主启动类OrderApplication

加上@EnableFeignClients开启了远程调用。

@EnableFeignClients
@MapperScan("com.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }
  • 自定义Feign客户端接口
@FeignClient("userservice")
public interface UserClient {

    @GetMapping("/user/{id}")
    User findById(@PathVariable("id") Long id);

}

controller接口注入UserClient接口并使用Feign发出http的Get请求查询用户。

@GetMapping("{orderId}")
    public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
        // 根据id查询订单并返回
        Order order = orderService.queryOrderById(orderId);

        //远程调用
//        User user = restTemplate.getForObject("http://user-service/user/" + order.getUserId(), User.class);

        //使用Feign发起http请求,查询用户
        User user = userClient.findById(order.getUserId());

        order.setUser(user);
        return order;
    }

这样代码优雅的可读性,成功调用并实现负载均衡~

3、Feign支持的配置

日志功能

日志级别:

BASIC:仅记录请求的方法,URL以及响应状态码和执行时间。

FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

HEADERS:记录请求的方法,URL以及响应状态码和执行时间,额外记录了请求和响应的头信息。

NONE:默认值,不记录任何日志信息。

自定义config/DefaultFeignConfiguration日志级别的配置类

@Configuration
public class DefaultFeignConfiguration {

    @Bean
    public Logger.Level feignLogLevel(){
        return Logger.Level.FULL;   //日志级别
    }

}

局部定义在远程接口上:

@FeignClient(value = "userservice", configuration = DefaultFeignConfiguration.class)

全局定义主启动类上:

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class)

application.yml

feign:
  client:
    config: default # 某个微服务userservice设置的日志, default全局日志
      loggerLevel: FULL # 日志级别

后台打印日志级别FULL效果:

 连接池

  • pom.xml
<!-- httpclient -->
        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>
  • application.yml
feign:
  httpclient:  # 连接池
    enabled: true # 开启feign对HttpClient的支持
    max-connections: 200 # 最大的连接数,默认200
    max-connections-per-route: 50  # 每个路径的最大连接数, 默认 50

feign底层通过httpClient进行负载均衡的过程:

 feign-api远程包

  • 新建feign-api模块

  •  pom.xml
<!-- openfeign -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

指定feign扫描服务包

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class, basePackages = "com.itcast.feign.client")

指定feign加载client服务接口

@EnableFeignClients(defaultConfiguration = DefaultFeignConfiguration.class, clients = {UserClient.class})

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

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

相关文章

批量插入数据、MVC三层分离

八、批量插入数据 1、使用Statement&#xff08;&#xff09; 2、使用PreparedStatement() 3、使用批量操作API 4、优化 九、MVC三层分离

Java中static关键字的作用

文章目录 一、使用static关键字修饰成员变量&#xff1a;二、使用static关键字修饰成员方法&#xff1a;三、使用static关键字定义静态代码块&#xff1a;四、使用static关键字定义内部类&#xff1a;五、使用静态导包&#xff1a;六、总结&#xff1a;static关键字在Java中有多…

大数据课程D7——hadoop的YARN

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 了解YARN的概念和结构&#xff1b; ⚪ 掌握YARN的资源调度流程&#xff1b; ⚪ 了解Hadoop支持的资源调度器&#xff1a;FIFO、Capacity、Fair&#xff1b; ⚪ 掌握YA…

Python语法(一、基础)

简介 Python 是一个高层次的结合了解释性、交互性和面向对象的脚本语言。解释型语言&#xff1a; 这意味着开发过程中没有了编译这个环节。作为解释型语言&#xff0c;意味着开发过程中没有了编译这个环节&#xff0c;对代码逐行解析。 Python还具有可嵌入性&#xff0c;如Py…

ConcurrentHashMap基本介绍

介绍 ConcurrentHashMap是线程安全且高效的HashMap。 为什么要使用ConcurrentHashMap 线程不安全的HashMap HashMap多线程情况下put操作会出现并发安全问题&#xff0c;包括死循环、数据丢失&#xff08;jdk7&#xff09;以及数据覆盖&#xff08;jdk8&#xff09;。 jdk7中…

基于stm32单片机的直流电机速度控制——LZW

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、实验目的二、实验方法三、实验设计1.实验器材2.电路连接3.软件设计&#xff08;1&#xff09;实验变量&#xff08;2&#xff09;功能模块a&#xff09;电机接收信号…

Github git clone 和 git push 特别慢的解决办法

1.在本地上使用 SSH 命令无法git push 上传 github 项目 2.使用 git clone 下载项目特别慢总是加载不了 解决办法1 将 *** 的连接模式换成&#xff1a;D-i-r-e-c-t&#xff08;好像不太有用&#xff09; 后面再找找能不能再G-l-o-b-a-l 下解决该问题 解决办法 2 mac下直接设…

Python 日志记录:6大日志记录库的比较

Python 日志记录&#xff1a;6大日志记录库的比较 文章目录 Python 日志记录&#xff1a;6大日志记录库的比较前言一些日志框架建议1. logging - 内置的标准日志模块默认日志记录器自定义日志记录器生成结构化日志 2. Loguru - 最流行的Python第三方日志框架默认日志记录器自定…

SpringBoot内嵌的Tomcat:

SpringBoot内嵌Tomcat源码&#xff1a; 1、调用启动类SpringbootdemoApplication中的SpringApplication.run()方法。 SpringBootApplication public class SpringbootdemoApplication {public static void main(String[] args) {SpringApplication.run(SpringbootdemoApplicat…

python浅浅替代ps?实现更改照片尺寸,以及更换照片底色

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 如何用代码来p证件照并且更换底色&#xff1f; 有个小姐姐给我扔了张照片&#xff0c;叫我帮忙给她搞成证件照的尺寸还得换底色 可惜电脑上没有ps只有pycharm&#xff0c;但下载又卸载多麻烦呀 于是&#xff0c;我就用代码来…

RT1052 的周期定时器

文章目录 1 PIT 周期中断定时器2 PIT定时器的使用3 PIT定时器配置3.1 PIT 时钟使能。3.1.1 CLOCK_EnableClock 3.2 初始化 PIT 定时器3.2.1 PIT_Init 3.3 设置 通道 0 的 加载值3.3.1 PIT_SetTimerPeriod 3.4 使能 通道 0 的中断3.4.1 PIT_EnableInterrupts 3.5 开启 PIT 定时器…

在登录界面中设置登录框、多选项和按钮(HTML和CSS)

登录框&#xff08;Input框&#xff09;的样式&#xff1a; /* 设置输入框的宽度和高度 */ input[type"text"], input[type"password"] {width: 200px;height: 30px; }/* 设置输入框的边框样式、颜色和圆角 */ input[type"text"], input[type&q…

测试|测试分类

测试|测试分类 文章目录 测试|测试分类1.按照测试对象分类&#xff08;部分掌握&#xff09;2.是否查看代码&#xff1a;黑盒、白盒灰盒测试3.按开发阶段分&#xff1a;单元、集成、系统及验收测试4.按实施组织分&#xff1a;α、β、第三方测试5.按是否运行代码&#xff1a;静…

100行代码写一个简易QT点名程序

照例演示一下: 分享一个简易的Qt点名程序&#xff0c;满打满算一百行代码&#xff08;还要什么自行车&#xff09;。 UI界面比较丑&#xff0c;按钮是自己做的&#xff0c;背景是AI作画生成的&#xff0c;大家可以自行更换背景以及按钮。 内容也是非常的简单&#xff0c;就是…

JWT登录认证

JWT认证流程 跨域认证解决方案&#xff0c;JWT的流程为&#xff1a; 客户端发送账号和密码请求服务端收到请求&#xff0c;验证用户名密码是否通过验证成功后&#xff0c;服务端会生成唯一的token&#xff0c;将其返回给客户端客户端收到token&#xff0c;会将其存储在cookie…

拓扑排序详解(带有C++模板)

目录 介绍&#xff1a; 实现原理&#xff1a; 简答来说&#xff1a; 例子 模板&#xff08;C&#xff09; 介绍&#xff1a; 拓扑排序&#xff08;Topological Sorting&#xff09;是一种针对有向无环图&#xff08;DAG&#xff09;的节点进行排序的算法。DAG是一个图&…

Android 之 使用 MediaRecord 录音

本节引言 本节是Android多媒体基本API调用的最后一节&#xff0c;带来的是MediaRecord的简单使用&#xff0c; 用法非常简单&#xff0c;我们写个例子来熟悉熟悉~ 1.使用MediaRecord录制音频 运行结果&#xff1a; 实现代码&#xff1a; 布局代码&#xff1a;activity_main.…

自动化测试如何做?真实企业自动化测试流程,自动化测试分类...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 企业自动化测试流…

一文讲清楚地图地理坐标系

前言 我最近在做一个和地图有关的项目&#xff0c;这里本人地图采用的是mapbox&#xff0c;其中涉及一个功能需要根据用户输入的地点直接定位到地图上的对应的位置&#xff0c;本人开始想的是直接调用百度的接口根据地名直接获取坐标&#xff0c;发现在地图上的位置有偏移不够…

C++——模板的作用2:特例化

目录 模板的形式&#xff1a; 一.模板的多参数应用&#xff1a; 例&#xff1a; 错误使用1&#xff1a;使用不标准的模板形参表 ​编辑 错误使用2&#xff1a;使用变量作为实参传递给函数模板 二.模板的特例化&#xff1a; 类模板&#xff1a; 针对模板的特化步骤&am…