简介

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

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.yan</groupId>
<artifactId>spring-cloud-ribbon</artifactId>
<version>1.0-SNAPSHOT</version> <parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>RELEASE</version>
</dependency>
</dependencies> </project>

配置

yml

server:
port: 8004
spring:
application:
name: spring-cloud-ribbon
cloud:
config:
discovery:
enabled: true
service-id: spring-cloud-config-server
profiles:
active: dev
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

启动类

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

package com.yan;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate; @SpringBootApplication
@Configuration
@EnableDiscoveryClient
public class RibbonApplication {
public static void main(String[] args) {
SpringApplication.run(RibbonApplication.class, args);
} @Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

Controller

package com.yan.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate; import java.util.StringJoiner; @RestController
@RequestMapping("/ribbon")
public class RibbonController {
private final RestTemplate template; @Autowired
public RibbonController(RestTemplate template) {
this.template = template;
} @GetMapping("/get")
public Object get(String svcName, String url, String className) {
Class<?> clazz = getResponseType(className);
String uri = getUrl(svcName, url);
return template.getForObject(uri, clazz);
} @PostMapping("/post")
public Object post(@RequestParam String svcName, @RequestParam String url, @RequestParam String className, @RequestBody HttpEntity<?> httpEntity) throws JsonProcessingException {
Class<?> clazz = getResponseType(className);
String url1 = getUrl(svcName, url);
Object res = template.postForObject(url1, httpEntity, clazz);
String resJson = new ObjectMapper().writeValueAsString(res);
System.out.println(resJson);
return res;
} private Class<?> getResponseType(@RequestParam String className) {
Class<?> clazz;
try {
clazz = Class.forName(className);
} catch (ClassNotFoundException e) {
clazz = String.class;
}
return clazz;
} private String getUrl(String svcName, String url) {
StringJoiner stringJoiner = new StringJoiner("/");
String uri = stringJoiner.add(svcName).add(url).toString().replaceAll("/+", "/");
return "http://" + uri;
} }

测试

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

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

打开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服务下看到日志:

"svcA:8081===>\nname:xixi\ntype:haha"
"svcA:8087===>\nname:xixi\ntype:haha"
"svcA:8081===>\nname:xixi\ntype:haha"
"svcA:8087===>\nname:xixi\ntype:haha"
"svcA:8081===>\nname:xixi\ntype:haha"
"svcA:8087===>\nname:xixi\ntype:haha"

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

最新文章

  1. 【AR实验室】ARToolKit之Example篇
  2. simple_html_dom配合snoopy使用
  3. 优先级反转实验,使用信号量实现【RT-Thread学习笔记 5】
  4. 从零开始学iPhone开发(2)——控件的使用
  5. Yaf零基础学习总结1-Yaf框架简介
  6. sql语句创建新登录名和设置权限
  7. JavaScript函数参数与调用
  8. C#:隔离点击任务栏上的图标时的“最小化或者恢复”的效果
  9. JAVA多线程和并发基础面试问答
  10. Java Volatile相关文章目录
  11. 清理sql2000查询分析器登录名记录
  12. YII Framework学习教程-YII的日志
  13. MySQL中字符串函数详细介绍
  14. jsp中如何获得url路径和绝对路径
  15. UNIX环保进程
  16. eclipse通过maven构建web项目步骤说明
  17. hdu 5667 BestCoder Round #80 矩阵快速幂
  18. input type=&quot;tel&quot; 数字输入框显示圆点
  19. Lesson 28 No parking
  20. 浏览器本地数据库 IndexedDB 基础详解

热门文章

  1. PAT-Top1002. Business (35)
  2. 四方定理(递归) --java
  3. Vmware下mint os的安装
  4. [原创]Burp Suite web应用程序渗透测试神器
  5. HTML动画 request animation frame
  6. SSE图像算法优化系列二十三: 基于value-and-criterion structure 系列滤波器(如Kuwahara,MLV,MCV滤波器)的优化。
  7. 科技论文之Latex公式&amp;amp;符号
  8. python接口自动化测试(八)-unittest-生成测试报告
  9. ABC卡
  10. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理