内容简介:交互图
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-server
、 order-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
了。假如使用 consul
、 zookeeper
、 etcd
等容器为服务发现为者时,就必须依赖 spring-cloud-starter-netflix-ribbon
包
<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 相关配置信息
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
注解(默认采用轮训算法)
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 可以自行尝试
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 了,而是写了一串字符,它是怎么做到的?
用通俗的概念来说,它就是编码与解码操作,还记得 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
假如我们不想使用轮训了,换换口味改成随机算法,又或者想自己写一套适合自己的负载算法,可以用下面这种方式
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 { }
总结
目前很多大佬都写过关于 Spring Cloud
的教程了,如有雷同,请多多包涵,本教程基于最新的 spring-cloud:Finchley.SR1
编写…
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Out of their Minds
Dennis Shasha、Cathy Lazere / Springer / 1998-07-02 / USD 16.00
This best-selling book is now available in an inexpensive softcover format. Imagine living during the Renaissance and being able to interview that eras greatest scientists about their inspirations, di......一起来看看 《Out of their Minds》 这本书的介绍吧!