简介

Spring Cloud Ribbon是一个基于Http和TCP的客户端负载均衡工具,它是基于Netflix Ribbon实现的。它不像服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每个微服务的基础设施中。理解Ribbon对于我们使用Spring Cloud来讲非常的重要,因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。

在Spring Cloud中,有两种服务调用方式,一种是Ribbon+RestTemplate,另一种是Feign。文本先讲解下基于Ribbon+RestTemplate的用法。

当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。

实现

新建服务spring-cloud-ribbon

pom.xml

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5. <modelVersion>4.0.0</modelVersion>
  6. <groupId>com.yan</groupId>
  7. <artifactId>spring-cloud-ribbon</artifactId>
  8. <version>1.0-SNAPSHOT</version>
  9. <parent>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-parent</artifactId>
  12. <version>2.1.0.RELEASE</version>
  13. <relativePath/>
  14. </parent>
  15. <dependencyManagement>
  16. <dependencies>
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-dependencies</artifactId>
  20. <version>Finchley.RELEASE</version>
  21. <type>pom</type>
  22. <scope>import</scope>
  23. </dependency>
  24. </dependencies>
  25. </dependencyManagement>
  26. <dependencies>
  27. <dependency>
  28. <groupId>org.springframework.cloud</groupId>
  29. <artifactId>spring-cloud-starter-ribbon</artifactId>
  30. <version>RELEASE</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.springframework.cloud</groupId>
  34. <artifactId>spring-cloud-starter-config</artifactId>
  35. <version>RELEASE</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>org.springframework.cloud</groupId>
  39. <artifactId>spring-cloud-starter-eureka</artifactId>
  40. <version>RELEASE</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.springframework.boot</groupId>
  44. <artifactId>spring-boot-starter-web</artifactId>
  45. <version>RELEASE</version>
  46. </dependency>
  47. </dependencies>
  48. </project>

配置

yml

  1. server:
  2. port: 8004
  3. spring:
  4. application:
  5. name: spring-cloud-ribbon
  6. cloud:
  7. config:
  8. discovery:
  9. enabled: true
  10. service-id: spring-cloud-config-server
  11. profiles:
  12. active: dev
  13. eureka:
  14. client:
  15. serviceUrl:
  16. defaultZone: http://localhost:8761/eureka/

启动类

核心是配有注解@LoadBalanced的RestTemplate的Bean配置

  1. package com.yan;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.cloud.client.loadbalancer.LoadBalanced;
  6. import org.springframework.context.annotation.Bean;
  7. import org.springframework.context.annotation.Configuration;
  8. import org.springframework.web.client.RestTemplate;
  9. @SpringBootApplication
  10. @Configuration
  11. @EnableDiscoveryClient
  12. public class RibbonApplication {
  13. public static void main(String[] args) {
  14. SpringApplication.run(RibbonApplication.class, args);
  15. }
  16. @Bean
  17. @LoadBalanced
  18. public RestTemplate restTemplate() {
  19. return new RestTemplate();
  20. }
  21. }

Controller

  1. package com.yan.controller;
  2. import com.fasterxml.jackson.core.JsonProcessingException;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.http.HttpEntity;
  6. import org.springframework.web.bind.annotation.*;
  7. import org.springframework.web.client.RestTemplate;
  8. import java.util.StringJoiner;
  9. @RestController
  10. @RequestMapping("/ribbon")
  11. public class RibbonController {
  12. private final RestTemplate template;
  13. @Autowired
  14. public RibbonController(RestTemplate template) {
  15. this.template = template;
  16. }
  17. @GetMapping("/get")
  18. public Object get(String svcName, String url, String className) {
  19. Class<?> clazz = getResponseType(className);
  20. String uri = getUrl(svcName, url);
  21. return template.getForObject(uri, clazz);
  22. }
  23. @PostMapping("/post")
  24. public Object post(@RequestParam String svcName, @RequestParam String url, @RequestParam String className, @RequestBody HttpEntity<?> httpEntity) throws JsonProcessingException {
  25. Class<?> clazz = getResponseType(className);
  26. String url1 = getUrl(svcName, url);
  27. Object res = template.postForObject(url1, httpEntity, clazz);
  28. String resJson = new ObjectMapper().writeValueAsString(res);
  29. System.out.println(resJson);
  30. return res;
  31. }
  32. private Class<?> getResponseType(@RequestParam String className) {
  33. Class<?> clazz;
  34. try {
  35. clazz = Class.forName(className);
  36. } catch (ClassNotFoundException e) {
  37. clazz = String.class;
  38. }
  39. return clazz;
  40. }
  41. private String getUrl(String svcName, String url) {
  42. StringJoiner stringJoiner = new StringJoiner("/");
  43. String uri = stringJoiner.add(svcName).add(url).toString().replaceAll("/+", "/");
  44. return "http://" + uri;
  45. }
  46. }

测试

假如我有两个名叫svcA的服务,同时注册到同一个Eureka上,只是端口号不同,它们都有一个post接口定义如下:

  1. @Value("${server.port}")
  2. private int port;
  3. @PostMapping("/post/{name}")
  4. public String post(@PathVariable String name, @RequestBody String type) {
  5. return "svcA:" + port + "===>\n" + "name:" + name + "\ntype:" + type;
  6. }

打开Postman:

发送请求:http://localhost:8004/ribbon/post?svcName=SVCA&url=/post/xixi&className=java.lang.String

Header:{'Content-Type': 'application/json'}

Body: {'raw': {

{

"headers": {"Content-Type": ["application/json"]},

"body": "haha"

}

}}

多次点击发送请求,在ribbon服务下看到日志:

  1. "svcA:8081===>\nname:xixi\ntype:haha"
  2. "svcA:8087===>\nname:xixi\ntype:haha"
  3. "svcA:8081===>\nname:xixi\ntype:haha"
  4. "svcA:8087===>\nname:xixi\ntype:haha"
  5. "svcA:8081===>\nname:xixi\ntype:haha"
  6. "svcA:8087===>\nname:xixi\ntype:haha"

两个服务交替接收请求,这说明Ribbon配置生效了。

Spring-Cloud-Ribbon学习笔记(一):入门的更多相关文章

  1. spring cloud(学习笔记)高可用注册中心(Eureka)的实现(二)

    绪论 前几天我用一种方式实现了spring cloud的高可用,达到两个注册中心,详情见spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一),今天我意外发现,注册中心可以无限 ...

  2. Spring Cloud Alibaba学习笔记(1) - 整合Spring Cloud Alibaba

    Spring Cloud Alibaba从孵化器版本毕业:https://github.com/alibaba/spring-cloud-alibaba,记录一下自己学习Spring Cloud Al ...

  3. Spring Cloud Alibaba学习笔记(3) - Ribbon

    1.手写一个客户端负载均衡器 在了解什么是Ribbon之前,首先通过代码的方式手写一个负载均衡器 RestTemplate restTemplate = new RestTemplate(); // ...

  4. spring cloud(学习笔记)高可用注册中心(Eureka)的实现(一)

    最近在学习的时候,发现微服务架构中,假如只有一个注册中心,那这个注册中心挂了可怎么办,这样的系统,既不安全,稳定性也不好,网上和书上找了一会,发现这个spring cloud早就想到了,并帮我们解决了 ...

  5. Spring Cloud Alibaba学习笔记(23) - 调用链监控工具Spring Cloud Sleuth + Zipkin

    随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请求可能最终需要调用很多次后端服务才能完成,当整个请求陷入性能瓶颈或不可用时,我们是无法得知该请求是由某个或某些后端服务引起的,这时就需要解决如何 ...

  6. Spring Cloud Alibaba学习笔记(20) - Spring Cloud Gateway 内置的全局过滤器

    参考:https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/single/spring-cloud.html#_global_filter ...

  7. Spring Cloud Alibaba学习笔记(15) - 整合Spring Cloud Gateway

    Spring Cloud Gateway 概述 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于Netty.Reactor以及WEbFlux构建,它 ...

  8. Spring Cloud Alibaba学习笔记(4) - Feign配置与使用

    什么是Feign Feign是一个声明式Web Service客户端. 使用Feign能让编写Web Service客户端更加简单, 它的使用方法是定义一个接口,然后在上面添加注解,同时也支持JAX- ...

  9. Spring Cloud Alibaba学习笔记

    引自B站楠哥:https://space.bilibili.com/434617924 一.创建父工程 创建父工程hello-spring-cloud-alibaba Spring Cloud Ali ...

  10. spring cloud(学习笔记)微服务启动错误(1)

    今天下午在启动spring cloud微服务的时候,报了这个错误: Error starting ApplicationContext. To display the auto-configurati ...

随机推荐

  1. css3实现不同的loading

    样式1: <html> <head> <style type="text/css"> .loading { position: fixed; t ...

  2. share_ptr_c++11

    C++智能指针 shared_ptr shared_ptr 是一个标准的共享所有权的智能指针, 允许多个指针指向同一个对象. 定义在 memory 文件中(非memory.h), 命名空间为 std. ...

  3. 【二分】Base Station Sites @ICPC2017HongKong/upcexam5559

    时间限制: 1 Sec 内存限制: 128 MB 5G is the proposed next telecommunications standards beyond the current 4G ...

  4. embOS ARM and Cortex Library Object and Symbol List

    OS_Alloc.o OS_free OS_Alloc.o OS_malloc OS_Alloc.o OS_realloc OS_ARM720_MMU.o OS_ARM720_CACHE_CleanR ...

  5. iOS:苹果内购实践

    iOS 苹果的内购 一.介绍 苹果规定,凡是虚拟的物品(例如:QQ音乐的乐币)进行交易时,都必须走苹果的内购通道,苹果要收取大约30%的抽成,所以不允许接入第三方的支付方式(微信.支付宝等),当然开发 ...

  6. AOP - C# Fody中的方法和属性拦截

    很久很久以前用过postsharp来做AOP, 大家知道的,现在那东东需要付费,于是尝试了一下Fody,但是发现Fody跟新太快了,所以大家在安装fody的时候尽力安装老的版本:packages.co ...

  7. redis批量删除key 远程批量删除key

    一.遇到的问题 在开发的过程中,经常会遇到要批量删除某种规则的key,如缓存的课程数据“course-课程uid”,其中课程uid是变量,我们需要删除"course-*"这一类的数 ...

  8. SSE图像算法优化系列二十八:深度优化局部拉普拉斯金字塔滤波器。

    基于局部拉普拉斯金字塔的Edge-aware滤波器是在2011年由Adobe 公司的研究员Sylvain Paris(大神级人物,写了很多文章)提出的,我在4年前曾经参考有关代码实现过这个算法,但是速 ...

  9. SSE图像算法优化系列二十一:基于DCT变换图像去噪算法的进一步优化(100W像素30ms)。

    在优化IPOL网站中基于DCT(离散余弦变换)的图像去噪算法(附源代码) 一文中,我们曾经优化过基于DCT变换的图像去噪算法,在那文所提供的Demo中,处理一副1000*1000左右的灰度噪音图像耗时 ...

  10. WPF参考

    web 调用本地exe 程序,传入参数https://www.cnblogs.com/anjou/p/10045177.html WPF常用控件样式https://www.cnblogs.com/s0 ...