【微服务】Ribbon的实现原理

news2025/1/9 22:37:05

1、场景:这里有两个服务,user-server和store-server

在这里插入图片描述

1.1、user服务

接口:

package com.lkx.user.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;


/**
 * @Author: lkx
 * @Date: 2023/8/23/13:20
 * @Description:
 */
@RestController
public class UserController {

    @GetMapping("/testUser")
    public Object testUser() {
        return "HelloWorld";
    }
}

1.2、store服务

配置类:

package com.lkx.store.config;

import org.springframework.boot.SpringBootConfiguration;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;

/**
 * @Author: lkx
 * @Date: 2023/8/23/13:18
 * @Description:
 */
@SpringBootConfiguration
@ComponentScan(basePackages = {"com.lkx.store"})
public class AppConfig {


    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

接口:

package com.lkx.store.controller;

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


/**
 * @Author: lkx
 * @Date: 2023/8/23/13:20
 * @Description:
 */
@RestController
public class StoreController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/testStore")
    public Object testStore() {
    	 /**
         * 原生调用方式实际上存在一种问题
         * 每多一次新地址的调用 都要维护一个全地址 这样维护起来相对就比较复杂了
         *
         * Ribbon :这个组件实际上就是为了来做服务的发现的
         * Ribbon最终服务的调用还是使用的是  restTemplate
    	 */
    	// 原生调用
        return restTemplate.getForObject("http://192.168.230.1:8081/testUser",String.class);
        // Ribbon调用
//        return restTemplate.getForObject("http://user-server/testUser",String.class);
    }
}

代码中,store服务通过url(ip地址加端口/方法)去调用user服务的接口,这是原生的调用方式。可以成功调用。Ribbon调用通过服务名称也可成功.

2、Ribbon的实现原理。

在这里插入图片描述
  解释:两个服务启动时,会将自己的服务名称,以及IP地址和端口注册到注册中心,当有服务调用时,就会拉取注册中心的注册表,里面包含了所有的注册信息。当我们使用Ribbon方式去调用其他服务时,ribbon的拦截器会拦截请求,然后根据拉取到的注册信息,去找到服务名称对应的ip地址和端口,然后重组请求地址,最后以原生的RestTemplate方式去实现服务的调用。

3、源码跟踪

配置类中,我们在设置Bean RestTemplate时,加了一个注解@LoadBalanced。这个注解尤为重要,它就是Ribbon实现原理最为重要的一环。

@LoadBalanced 源码:

/*
 * Copyright 2013-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.client.loadbalancer;

import org.springframework.beans.factory.annotation.Qualifier;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient.
 * @author Spencer Gibb
 */
@Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Qualifier
public @interface LoadBalanced {
}

这里的解释翻译是:标记一个RestTemplate bean来配置使用LoadBalancerClient。那么,这个LoadBalancerClient是什么呢?

/*
 * Copyright 2013-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.client.loadbalancer;

import org.springframework.cloud.client.ServiceInstance;

import java.io.IOException;
import java.net.URI;

/**
 * Represents a client-side load balancer.
 * @author Spencer Gibb
 */
public interface LoadBalancerClient extends ServiceInstanceChooser {

	/**
	 * Executes request using a ServiceInstance from the LoadBalancer for the specified
	 * service.
	 * @param serviceId The service ID to look up the LoadBalancer.
	 * @param request Allows implementations to execute pre and post actions, such as
	 * incrementing metrics.
	 * @return The result of the LoadBalancerRequest callback on the selected
	 * ServiceInstance.
	 */
	<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

	/**
	 * Executes request using a ServiceInstance from the LoadBalancer for the specified
	 * service.
	 * @param serviceId The service ID to look up the LoadBalancer.
	 * @param serviceInstance The service to execute the request to.
	 * @param request Allows implementations to execute pre and post actions, such as
	 * incrementing metrics.
	 * @return The result of the LoadBalancerRequest callback on the selected
	 * ServiceInstance.
	 */
	<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;

	/**
	 * Creates a proper URI with a real host and port for systems to utilize.
	 * Some systems use a URI with the logical service name as the host,
	 * such as http://myservice/path/to/service.  This will replace the
	 * service name with the host:port from the ServiceInstance.
	 * @param instance
	 * @param original A URI with the host as a logical service name.
	 * @return A reconstructed URI.
	 */
	URI reconstructURI(ServiceInstance instance, URI original);
}

翻译一下注释:Represents a client-side load balancer.这是一个客户端负载平衡器。而@LoadBalanced注解标记的RestTemplate就是来配置这个平衡器的,这里我们就需要找到这个配置类,同文件夹下有一个LoadBalancerAutoConfiguration,给它的解释是功能区的自动配置(客户端负载平衡)


	@Configuration
	@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
	static class LoadBalancerInterceptorConfig {
		@Bean
		public LoadBalancerInterceptor ribbonInterceptor(
				LoadBalancerClient loadBalancerClient,
				LoadBalancerRequestFactory requestFactory) {
			return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
		}

		@Bean
		@ConditionalOnMissingBean
		public RestTemplateCustomizer restTemplateCustomizer(
				final LoadBalancerInterceptor loadBalancerInterceptor) {
			return restTemplate -> {
                List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                        restTemplate.getInterceptors());
                list.add(loadBalancerInterceptor);
                restTemplate.setInterceptors(list);
            };
		}
	}

而在这个配置类里就有我们的ribbon的拦截器设置了。然后进入LoadBalancerInterceptor拦截器,通过拦截器的执行代码,然后到RibbonLoadBalancerClient的execute方法,这个方法就是通过我们的key来找到对应的服务器去执行请求,后面方法太多,就不一 一叙述,最后发现,最底层调用的还是原生的请求去实现调用的。

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

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

相关文章

【vue+uniapp】切换本页面(点击导航按钮)就刷新接口

查阅资料&#xff1a;uni-app官网 点击导航中图标&#xff0c;就执行的方法&#xff08;和methods同级&#xff09;&#xff1a; onTabItemTap(e) {this.getTaskTotal(); },

ubuntu执行jmeter端口不够用报错(Address not available)

ubuntu执行jmeter端口不够用报错(Address not available) 解决方案 // 增加本地端口范围 echo 1024 65000 > /proc/sys/net/ipv4/ip_local_port_range// 启用快速回收TIME_WAIT套接字 sudo sysctl -w net.ipv4.tcp_tw_recycle 1// 启用套接字的重用 sudo sysctl -w net.ipv4…

LLMs 缩放法则和计算最优模型Scaling laws and compute-optimal models

在上一个视频中&#xff0c;您探讨了训练大型语言模型的计算挑战。在这里&#xff0c;您将了解关于模型大小、训练、配置和性能之间关系的研究&#xff0c;以确定模型需要多大。请记住&#xff0c;预训练期间的目标是最大化模型的学习目标性能&#xff0c;即在预测令牌时最小化…

【LeetCode-中等题】53. 最大子数组和

题目 题解一&#xff1a;暴力解法&#xff1a; //暴力解法 每个元素为都循环一次&#xff0c;持续更新最大值int maxS Integer.MIN_VALUE;for(int i 0;i<nums.length;i){int num 0;for(int j i;j<nums.length;j){num numnums[j];maxS Math.max(maxS,num);}}retur…

数据库——事务,事务隔离级别

文章目录 什么是事务?事务的特性(ACID)并发事务带来的问题事务隔离级别实际情况演示脏读(读未提交)避免脏读(读已提交)不可重复读可重复读防止幻读(可串行化) 什么是事务? 事务是逻辑上的一组操作&#xff0c;要么都执行&#xff0c;要么都不执行。 事务最经典也经常被拿出…

DNQ算法原理(Deep Q Network)

1.强化学习概念 学习系统没有像很多其它形式的机器学习方法一样被告知应该做出什么行为 必须在尝试了之后才能发现哪些行为会导致奖励的最大化 当前的行为可能不仅仅会影响即时奖励&#xff0c;还会影响下一步的奖励以及后续的所有奖励 每一个动作(action)都能影响代理将来的…

Java中Date日期类的使用方法

一、构造器实例化对象 //使用无参构造器 Date date1 new Date(); System.out.println(date1);//使用有参构造器&#xff0c;参数为long类型的时间戳&#xff0c;将时间戳自动转为时间对象 Date date2 new Date(60000); System.out.println(date2); 运行结果&#xff1a; 说…

直击软博会|润和软件国产操作系统HopeStage助力行业数字化实践

2023年8月22日下午&#xff0c;2023中国&#xff08;南京&#xff09;软博会信息技术应用创新大会在南京国际博览会议中心顺利召开&#xff0c;润和软件作为信创操作系统领域的核心力量受邀参会并发表演讲。 会上&#xff0c;润和软件云计算事业部总经理蔡志旻发表了《HopeStag…

电压放大器有什么特点和作用

电压放大器是一种常见的电子设备&#xff0c;具有许多特点和作用。下面安泰电子来详细介绍电压放大器的特点和作用。 电压放大器具有以下几个特点&#xff1a; 增益高&#xff1a;电压放大器能够将输入信号的电压放大到较高的水平。这意味着它可以增加信号的强度&#xff0c;使…

身份证号、姓名脱敏(*隐藏关键信息)

// 过滤器 filters: {// 加密身份证明号码encryptSfzmhmHandler(val) {// 加密年月日return val ? val.replace(val.slice(6, -4), ********) : }// 加密姓名encryptXmHandler(val) {let value if (val && val.length 2) {// 两个字的*最后一个字value val.replace…

数据管道的重要性:为什么您需要关注!

一、引言 在当今的信息时代&#xff0c;数据已经成为了企业的生命线。无论是商业决策&#xff0c;还是产品研发&#xff0c;都离不开对数据的依赖。然而&#xff0c;如何有效地管理和使用这些数据&#xff0c;却是许多企业面临的难题。这时&#xff0c;数据管道的重要性就显现出…

四川玖璨电子商务有限公司:短视频运营的关键

​短视频运营作为当前互联网行业的热点之一&#xff0c;具有广阔的发展前景。然而&#xff0c;要在激烈的竞争中脱颖而出&#xff0c;就需要掌握一些关键点。下面将从内容创作、用户增长、社交互动和商业变现等几个方面来探讨短视频运营的关键。 一、内容创作。 内容是短视频…

【leetcode 力扣刷题】交换链表中的节点

24. 两两交换链表中的节点 24. 两两交换链表中的节点两两节点分组&#xff0c;反转两个节点连接递归求解 24. 两两交换链表中的节点 题目链接&#xff1a;24. 两两交换链表中的节点 题目内容&#xff1a; 题目中强调不能修改节点内部值&#xff0c;是因为如果不加这个限制的话…

跨境电商shopee平台怎么样?Shopee选品工具是什么?

跨境电商shopee平台市场可以说是相当活跃和竞争激烈的电商市场。作为东南亚地区最大的电商平台之一&#xff0c;跨境电商shopee平台覆盖了多个国家和地区&#xff0c;包括新加坡、马来西亚、泰国、印度尼西亚、越南、菲律宾和台湾。 跨境电商shopee平台市场的活跃程度体现在以下…

广州华锐互动:3D航天科学网上展馆让你沉浸式体验航天文化

3D航天科学网上展馆是一种利用先进的3D技术和虚拟现实技术展示航天科技的场所。与传统的展馆相比&#xff0c;3D航天科学网上展馆具有许多独特的特色。以下是3D航天科学网上展馆的一些主要特色&#xff1a; 1.沉浸式体验&#xff1a;3D航天科学网上展馆通过虚拟现实技术为观众提…

Windows10查看图片的分辨率

文章目录 查看方法 查看方法 鼠标悬停在想查看分辨率大小的图片上&#xff0c;稍等那么零点几秒&#xff0c;就会弹出图片的分辨率信息&#xff0c;如图所示&#xff1a;

单片机系统的电磁兼容设计

目录 1.什么是单片机 2.单片机的应用领域 3.单片机系统常见的电磁干扰 4.电磁干扰对单片机造成的影响 5.如何消除单片机系统的电磁干扰 1.什么是单片机 单片机是一种集成电路芯片&#xff0c;也被称为微控制器。它集成了中央处理器&#xff08;CPU&#xff09;、存储器、输…

湘潭大学 湘大 XTU OJ 1441 平衡三进制2 题解(非常详细)

前置知识 很多时候我们觉得一件事情难&#xff0c;其实并不是这一整件事情难&#xff0c;而是中间有一部分&#xff08;极端情况是几乎所有&#xff09;东西我们不知道&#xff0c;没有相关的经验&#xff0c;所以我们不断地学习 这道题目的前置知识是十进制转三进制怎么转换…

朋友圈发圈文案防折叠不折叠转换流量主小程序开发

朋友圈发圈文案防折叠不折叠转换流量主小程序开发 不折叠&#xff1a;转发此条动态&#xff0c;帮我解锁朋友圈新技能&#xff0c;让你的朋友圈更加精彩&#xff01;折叠转不折叠&#xff1a;转发此动态&#xff0c;即可开启朋友圈折叠转不折叠的功能&#xff0c;让你的朋友圈…

第七章 类、结构体、指针与引用

目录 1.基础知识2.练习题2.1 斐波那契数列2.2 替换空格2.3 求12…n2.3.1 方法一&#xff1a;2.3.2 方法二&#xff1a; 2.4 在O(1)时间删除链表结点2.5 合并两个排序的链表2.6 左旋转字符串2.7 把字符串转换成整数2.8 反转链表2.9 两个链表的第一个公共结点2.10 删除链表中重复…