SpringCloud 系列 --3. 负载均衡 @LoadBalanced 注解原理

本贴最后更新于 1839 天前,其中的信息可能已经斗转星移
restTemplate本身不具有负载均衡原理,但是加入了@LoadBalanced注解后具有负载功能,得益于RestTemplate的拦截器功能. 我们模拟实现一个自定义的@LoadBalanced注解 @MyLoadBalanced
package org.crazyit.cloud; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.beans.factory.annotation.Qualifier; @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface MyLoadBalanced { }
然后实现org.springframework.http.HttpRequest 接口,将原先的URI进行重写,所有的请求转发到http://localhost:8080/hello这个地址. SpringCloud对RestTemplate进行拦截时候也做了同样的事情,只不过更加灵活的处理,并不是像我们返回固定的URI。
package org.crazyit.cloud; import java.net.URI; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpRequest; /** * 自定义的请求类,用于转换URI * @author 杨恩雄 * */ public class MyHttpRequest implements HttpRequest { private HttpRequest sourceRequest; public MyHttpRequest(HttpRequest sourceRequest) { this.sourceRequest = sourceRequest; } public HttpHeaders getHeaders() { return sourceRequest.getHeaders(); } public HttpMethod getMethod() { return sourceRequest.getMethod(); } /** * 将URI转换 */ public URI getURI() { try { URI newUri = new URI("http://localhost:8080/hello"); return newUri; } catch (Exception e) { e.printStackTrace(); } return sourceRequest.getURI(); } }

然后我们自定义拦截器, 将原先请求使用我们刚才定义的 MyHttpRequest 进行转换.

package org.crazyit.cloud; import java.io.IOException; import org.springframework.http.HttpRequest; import org.springframework.http.client.ClientHttpRequestExecution; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.http.client.ClientHttpResponse; /** * 自定义拦截器 * * @author 杨恩雄 * */ public class MyInterceptor implements ClientHttpRequestInterceptor { public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException { System.out.println("============= 这是自定义拦截器实现"); System.out.println(" 原来的URI:" + request.getURI()); // 换成新的请求对象(更换URI) MyHttpRequest newRequest = new MyHttpRequest(request); System.out.println(" 拦截后新的URI:" + newRequest.getURI()); return execution.execute(newRequest, body); } }

配置在容器启动的时候将我们的自定义拦截器 MyInterceptor 加入到 RestTemplate 实例中

package org.crazyit.cloud; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestInterceptor; import org.springframework.web.client.RestTemplate; @Configuration public class MyAutoConfiguration { @Autowired(required=false) @MyLoadBalanced private List<RestTemplate> myTemplates = Collections.emptyList(); @Bean public SmartInitializingSingleton myLoadBalancedRestTemplateInitializer() { System.out.println("==== 这个Bean将在容器初始化时创建 ====="); return new SmartInitializingSingleton() { public void afterSingletonsInstantiated() { for(RestTemplate tpl : myTemplates) { // 创建一个自定义的拦截器实例 MyInterceptor mi = new MyInterceptor(); // 获取RestTemplate原来的拦截器 List list = new ArrayList(tpl.getInterceptors()); // 添加到拦截器集合 list.add(mi); // 将新的拦截器集合设置到RestTemplate实例 tpl.setInterceptors(list); } } }; } }

最后使用我们的注解 @MyLoadBalanced

package org.crazyit.cloud; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController @Configuration public class InvokerController { @Bean @MyLoadBalanced public RestTemplate getMyRestTemplate() { return new RestTemplate(); } /** * 浏览器访问的请求 */ @RequestMapping(value = "/router", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE) public String router() { RestTemplate restTpl = getMyRestTemplate(); // 根据名称来调用服务,这个URI会被拦截器所置换 String json = restTpl.getForObject("http://my-server/hello", String.class); return json; } /** * 最终的请求都会转到这个服务 */ @RequestMapping(value = "/hello", method = RequestMethod.GET) @ResponseBody public String hello() { return "Hello World"; } }

启动类

package org.crazyit.cloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class TestInterceptorMain { public static void main(String[] args) { SpringApplication.run(TestInterceptorMain.class, args); } }

最后访问 http://localhost:8080/router 本来访问 http://my-server/hello
但是现在不管 my-server 原先是哪个地址都会转发到 localhost:8080/hello 这里。

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    946 引用 • 1460 回帖
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 6 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • NGINX

    NGINX 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器。 NGINX 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,第一个公开版本 0.1.0 发布于 2004 年 10 月 4 日。

    315 引用 • 547 回帖
  • 快应用

    快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。

    15 引用 • 127 回帖
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 254 关注
  • OpenResty

    OpenResty 是一个基于 NGINX 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

    17 引用 • 56 关注
  • 反馈

    Communication channel for makers and users.

    126 引用 • 929 回帖 • 266 关注
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖 • 2 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 788 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖
  • 钉钉

    钉钉,专为中国企业打造的免费沟通协同多端平台, 阿里巴巴出品。

    15 引用 • 67 回帖 • 295 关注
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    173 引用 • 414 回帖 • 369 关注
  • Tomcat

    Tomcat 最早是由 Sun Microsystems 开发的一个 Servlet 容器,在 1999 年被捐献给 ASF(Apache Software Foundation),隶属于 Jakarta 项目,现在已经独立为一个顶级项目。Tomcat 主要实现了 JavaEE 中的 Servlet、JSP 规范,同时也提供 HTTP 服务,是市场上非常流行的 Java Web 容器。

    162 引用 • 529 回帖 • 1 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 165 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    189 引用 • 1057 回帖 • 1 关注
  • 服务器

    服务器,也称伺服器,是提供计算服务的设备。由于服务器需要响应服务请求,并进行处理,因此一般来说服务器应具备承担服务并且保障服务的能力。

    125 引用 • 585 回帖
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖
  • Firefox

    Mozilla Firefox 中文俗称“火狐”(正式缩写为 Fx 或 fx,非正式缩写为 FF),是一个开源的网页浏览器,使用 Gecko 排版引擎,支持多种操作系统,如 Windows、OSX 及 Linux 等。

    7 引用 • 30 回帖 • 395 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 207 关注
  • JavaScript

    JavaScript 一种动态类型、弱类型、基于原型的直译式脚本语言,内置支持类型。它的解释器被称为 JavaScript 引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在 HTML 网页上使用,用来给 HTML 网页增加动态功能。

    729 引用 • 1278 回帖
  • 一些有用的避坑指南。

    69 引用 • 93 回帖
  • Log4j

    Log4j 是 Apache 开源的一款使用广泛的 Java 日志组件。

    20 引用 • 18 回帖 • 33 关注
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    426 引用 • 1250 回帖 • 599 关注
  • AWS
    11 引用 • 28 回帖 • 11 关注
  • Hexo

    Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。

    22 引用 • 148 回帖 • 10 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    179 引用 • 408 回帖 • 485 关注
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    226 引用 • 476 回帖
  • FlowUs

    FlowUs.息流 个人及团队的新一代生产力工具。

    让复杂的信息管理更轻松、自由、充满创意。

    1 引用