Spring Cloud 为开发者提供了在分布式系统中的一些常用的组件(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁定,决策竞选,分布式会话集群状态)。使用Spring Cloud开发人员可以快速地完成实现这些模式的服务和应用程序。它们在任何分布式环境中都能很好地工作

Ribbon

Ribbon 是 Netflix 开源的基于 HTTP 和 TCP 的客户端负载均衡器框架,目前也已被 Spring Cloud 团队集成在 spring-cloud-netflix子项目下,主要用于客户端软负载功能,内部已实现了 随机轮训权重减压(选取压力最小的) 等常见的负载算法,同时也提供了 ILoadBalance 与 IRule 两个接口方便我们自己编写适合自己的负载算法

  • 负载均衡
  • 容错
  • 多协议(HTTP,TCP,UDP)支持异步和反应模型
  • 缓存和批处理

交互图

交互图

Try

要尝试 Spring Cloud Ribbon 首要的就是准备一个服务注册中心,还不太清楚的可以在回头看看上一章 认识Eureka ,这里就不做过多赘述了,准备 eureka-server(回顾上一章)product-serverorder-server 三个项目,后面的两个可以理解为上一章的 eureka-client

Eureka Server

详情参考上一章,或从文末的 GITHUB 链接获取对应篇幅的完整代码

Product Server

一个普通的 Eureka Client 即可,详情参考上一章,或从文末的 GITHUB 链接获取对应篇幅的完整代码

Order Server

一个普通的 Eureka Client

依赖

细心的小伙伴会发现,这和一个普通的 Eureka Client 也没啥区别啊,没任何额外依赖的,那是因为在 spring-cloud-starter-netflix-eureka-client 中已经帮我们依赖过 spring-cloud-starter-netflix-ribbon 了。假如使用 consulzookeeperetcd 等容器为服务发现为者时,就必须依赖 spring-cloud-starter-netflix-ribbon 包

1
2
3
4
5
6
7
8
9
10
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>

配置文件

在 src/main/resources 目录下创建一个 bootstrap.yml 的文件,写上 eureka 相关配置信息

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 7072
spring:
application:
name: order-server
eureka:
instance:
prefer-ip-address: true
instance-id: ${spring.cloud.client.ip-address}:${spring.application.instance_id:${server.port}}
client:
service-url:
defaultZone: http://localhost:7071/eureka/

主函数

各位小伙伴对 Spring Boot 中的 RestTemplate 应该都不陌生,它是由 Spring Boot 提供而不是 Spring Cloud ,无负载功能,为了方便开发者,Spring Cloud 团队提供了一个 @LoadBalanced 注解(默认采用轮训算法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.battcn;

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; /**
* @author Levin
*/
@EnableDiscoveryClient
@SpringBootApplication
public class OrderApplication { @Configuration
class MyConfiguration {
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
} public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}

控制器

客户端(order-server:7702)从 Eureka Server 同步了 product-server:7703 和 product-server:7704 这个时候它是如何知晓注册表中的信息呢?上一章中遗留了一个知识点就是 DiscoveryClient ,通过它就可以获得注册表中客户端的信息了,下列代码块演示了 DiscoveryClient 的简单用法,更多 API 可以自行尝试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.battcn.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate; import java.util.List; /**
* @author Levin
* @since 2018/9/28 0028
*/
@RestController
@RequestMapping("/orders")
public class OrderController { private final RestTemplate restTemplate;
private final DiscoveryClient discoveryClient; @Autowired
public OrderController(RestTemplate restTemplate, DiscoveryClient discoveryClient) {
this.restTemplate = restTemplate;
this.discoveryClient = discoveryClient;
} @GetMapping
public String query() {
final List<String> services = discoveryClient.getServices();
for (String service : services) {
List<ServiceInstance> list = discoveryClient.getInstances(service);
for (ServiceInstance instance : list) {
System.out.println(instance.getUri() + "/" + service + " - " + instance.getServiceId());
}
}
return restTemplate.getForObject("http://PRODUCT-SERVER/products", String.class);
}
}

Why

有的小伙伴对上面的内容会存在一些疑问,为什么没有写 IP:PORT 了,而是写了一串字符,它是怎么做到的?

1
2
3
4
5
6
7
8
9
10
11
12
13
用通俗的概念来说,它就是编码与解码操作,还记得 Eureka Server UI 中 Application 吗? 
编码:根据 spring.application.name 设置 serviceId
Server ID:PRODUCT-SERVER
Client A :http://localhost:7073/products
Client B :http://localhost:7074/products 解码:通过 serviceId 找到对应的客户端,
然后根据客户端配置的负载算法从对应集合中
找出符合当前算法条件的结果,最后拼接出相应的 http 地址即可 解码前:http://PRODUCT-SERVER/products
那么将 http://PRODUCT-SERVER 替换成 instance.getUri() 内容是不是就出来了
http://localhost:7073/products 和 http://localhost:7074/products

效果图

自定义 IRule

假如我们不想使用轮训了,换换口味改成随机算法,又或者想自己写一套适合自己的负载算法,可以用下面这种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.battcn.config;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; /**
* @author Levin
* @since 2018/9/28 0028
*/
@Configuration
public class RibbonRuleConfiguration { @Bean
public IRule ribbonRule() {
return new RandomRule();
}
} @RibbonClient(name = "ribbonRule",configuration = RibbonRuleConfiguration.class)
public class OrderController { }

最新文章

  1. 20155324王鸣宇对C语言课程回顾及对Java的展望
  2. python 类属性与方法
  3. AgileEAS.NET SOA 中间件平台5.2版本下载、配置学习(一):下载平台并基于直连环境运行
  4. Molecule – 帮助你构建跨平台的 HTML5 游戏
  5. iOS- 利用AFNetworking3.0+(最新AFN) - 实现文件断点下载
  6. ARP侦查工具Netdiscover
  7. Projective Texture的原理与实现
  8. [转] git修改author
  9. BZOJ1532: [POI2005]Kos-Dicing
  10. Vue2.x中的父组件数据传递至子组件
  11. SpringBoot(一):使用eclipse/idea创建springboot helloword工程
  12. 与MP3相关的技术总结
  13. Oracle 给予访问其他用户包的权限
  14. sealed关键字
  15. Vue性能优化
  16. MIT Molecular Biology 笔记3 DNA同源重组
  17. fork(), waitpid()
  18. sqoop2启动client异常
  19. CC2540 OSAL 学习其中原理,以及 给任务 添加 一个事件(定时发送串口消息)
  20. c/c++中system函数在Linux和windows下区别

热门文章

  1. Java实现 LeetCode 736 Lisp 语法解析(递归)
  2. Java实现 LeetCode 398 随机数索引
  3. SQL Server实现 LeetCode 178 分数排名
  4. java实现第七届蓝桥杯分小组
  5. java实现第四届蓝桥杯梅森素数
  6. TZOJ Start
  7. BFART算法
  8. 异步函数async await在wpf都做了什么?
  9. cnblogs 博客爬取 + scrapy + 持久化 + 分布式
  10. 关于thinkphp5下URL附加参数,无法获取到(?参数)