Spring Cloud Netflix Ribbon核心接口
Spring Cloud Netflix Ribbon核心接口
LoadBalancerClient
主要职责
- 转化URI:将含应用名称URI转化成具体主机+端口形式
- 选择服务实例:通过负载算法,选择指定服务中的一台机器实例
- 请求执行回调:针对选择后服务实例,执行具体的请求回调操作
默认实现:RibbonLoadBalancerClient
自动装配源:RibbonAutoConfiguration#loadBalancerClient(...)
负载均衡器上下文
LoadBalancerContext
主要职责
- 转化URI:将含应用名称URI转化成具体主机+端口的形式
- 组件关联:关联RetryHandler、ILoadBalancer等
- 记录服务统计信息:记录请求响应时间、错误数量等
- 默认实现:RibbonLoadBalancerContext
- 自动装配源:RibbonClientConfiguration#ribbonLoadBalancerContext(...)
负载均衡器
ILoadBalancer
主要职责
- 增加服务器
- 获取服务器:通过关联Key获取、获取所有服务列表、获取可用服务器列表
- 服务器状态:标记服务器宕机
- 默认实现:ZoneAwareLoadBalancer
- 自动装配源:RibbonClientConfiguration#ribbonLoadBalancer(...)
规则接口
IRule
主要职责
- 选择服务器:根据负载均衡器以及关联Key获取候选的服务器
- 默认实现:ZoneAvoidanceRule
- 自动装配源:RibbonClientConfiguration#ribbonRule(...)
PING策略
IPing
主要职责
- 活动检测:根据指定的服务器,检测其是否活动
- 默认实现:DummyPing
- 自动装配源:RibbonClientConfiguration#ribbonPing(...)
服务器列表
ServerList
主要职责
- 获取初始化服务器列表
- 获取更新服务器列表
- 默认实现:ConfigurationBasedServerList或DiscoveryEnabledNIWSServerList
- 自动装配源:RibbonClientConfiguration#ribbonPing(...)
我的项目版本信息Maven配置
<?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> <modules> <module>user-api</module> </modules> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.example</groupId> <artifactId>spring-cloud-lesson-7</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <name>spring-cloud-lesson-7</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <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> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
idea多工程配置
pom.xml文件中
然后删除之前src文件夹,然后new个项目,效果如图
三个模块:
- user-api:公用 API
- user-ribbon-client:客户端应用
- user-service-provider:服务端应用
实现 user-robbon-client
配置信息
application.properties:
## 用户 Ribbon 客户端应用 spring.application.name = user-ribbon-client ## 服务端口 server.port = 8080 ## 提供方服务名称 provider.service.name = user-service-provider ## 提供方服务主机 provider.service.host = localhost ## 提供方服务端口 provider.service.port = 9090 ## 关闭 Eureka Client,显示地通过配置方式注册 Ribbon 服务地址 eureka.client.enabled = false ## 定义 user-service-provider Ribbon 的服务器地址 ## 为 RibbonLoadBalancerClient 提供服务列表 user-service-provider.ribbon.listOfServers = \ http://${provider.service.host}:${provider.service.port}
2.编写客户端调用
package com.segumentfault.spring.cloud.lesson7.user.ribbon.client.web.controller; import com.segumentfault.spring.cloud.lesson7.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import javax.ws.rs.GET; import java.io.IOException; /** * 用户 Ribbon Controller * */ @RestController public class UserRibbonController { /** * 负载均衡器客户端 */ @Autowired private LoadBalancerClient loadBalancerClient; @Value("${provider.service.name}") private String providerServiceName; @GetMapping("") public String index() throws IOException { User user = new User(); user.setId(1L); user.setName("ssss"); // 选择指定的 service Id ServiceInstance serviceInstance = loadBalancerClient.choose(providerServiceName); return loadBalancerClient.execute(providerServiceName, serviceInstance, instance -> { //服务器实例,获取 主机名(IP) 和 端口 String host = instance.getHost(); int port = instance.getPort(); String url = "http://" + host + ":" + port + "/user/save"; RestTemplate restTemplate = new RestTemplate(); return restTemplate.postForObject(url, user, String.class); }); } }
3.编写引导类
package com.segumentfault.spring.cloud.lesson7.user.ribbon.client; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.ribbon.RibbonClient; /** * 引导类 * */ @SpringBootApplication @RibbonClient("user-service-provider") // 指定目标应用名称 public class UserRibbonClientApplication { public static void main(String[] args) { SpringApplication.run(UserRibbonClientApplication.class, args); } }
实现user-service-provider
1.配置信息
application.properties
## 用户服务提供方应用信息 spring.application.name = user-service-provider ## 服务端口 server.port = 9090 ## 关闭 Eureka Client,显示地通过配置方式注册 Ribbon 服务地址 eureka.client.enabled = false
2.实现UserService
package com.segumentfault.spring.cloud.lesson7.user.service.provider.service; import com.segumentfault.spring.cloud.lesson7.api.UserService; import com.segumentfault.spring.cloud.lesson7.domain.User; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * 内存实现{@link UserService} * */ @Service public class InMemoryUserService implements UserService { private Map<Long, User> repository = new ConcurrentHashMap<>(); @Override public boolean saveUser(User user) { return repository.put(user.getId(), user) == null; } @Override public List<User> findAll() { return new ArrayList(repository.values()); } }
3.实现Web服务
package com.segumentfault.spring.cloud.lesson7.user.service.web.controller; import com.segumentfault.spring.cloud.lesson7.api.UserService; import com.segumentfault.spring.cloud.lesson7.domain.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; /** * 用户服务提供方 Controller * */ @RestController public class UserServiceProviderController { @Autowired private UserService userService; @PostMapping("/user/save") public boolean user(@RequestBody User user){ return userService.saveUser(user); } }
4.编写引导类
package com.segumentfault.spring.cloud.lesson7.user.service; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.ribbon.RibbonClient; /** * 引导类 * */ @SpringBootApplication public class UserServiceProviderApplication { public static void main(String[] args) { SpringApplication.run(UserServiceProviderApplication.class, args); } }
下面知识点是拓展源码练习,只做了解
分析调用链路
选择服务器逻辑
LoadBalancerClient(LoadBalancerClient) -> ILoadBalancer(ZoneAwareLoadBalancer) -> IRule (ZoneAvoidanceRule)
自定义实现IRule
扩展AbstractLoadBalancerRule:MyRule
package com.segumentfault.spring.cloud.lesson7.user.ribbon.client.rule; import com.netflix.client.config.IClientConfig; import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.ILoadBalancer; import com.netflix.loadbalancer.IRule; import com.netflix.loadbalancer.Server; import java.util.List; /** * 自定义{@link IRule} 实现,永远选择最后一台可达服务器 * */ public class MyRule extends AbstractLoadBalancerRule { @Override public void initWithNiwsConfig(IClientConfig clientConfig) { } @Override public Server choose(Object key) { ILoadBalancer loadBalancer = getLoadBalancer(); //获取所有可达服务器列表 List<Server> servers = loadBalancer.getReachableServers(); if (servers.isEmpty()) { return null; } // 永远选择最后一台可达服务器 Server targetServer = servers.get(servers.size() - 1); return targetServer; } }
将MyRule暴露成Bean
通过ribbonClientConfiguration
学习源码
@Bean @ConditionalOnMissingBean public IRule ribbonRule(IClientConfig config) { if (this.propertiesFactory.isSet(IRule.class, name)) { return this.propertiesFactory.get(IRule.class, config, name); } ZoneAvoidanceRule rule = new ZoneAvoidanceRule(); rule.initWithNiwsConfig(config); return rule; }
然后将其暴露成Bean
/** * 将 {@link MyRule} 暴露成 {@link Bean} * * @return {@link MyRule} */ @Bean public IRule myRule() { return new MyRule(); }
配置化实现组件
通过学习PropertiesFactory
源码
public PropertiesFactory() { classToProperty.put(ILoadBalancer.class, "NFLoadBalancerClassName"); classToProperty.put(IPing.class, "NFLoadBalancerPingClassName"); classToProperty.put(IRule.class, "NFLoadBalancerRuleClassName"); classToProperty.put(ServerList.class, "NIWSServerListClassName"); classToProperty.put(ServerListFilter.class, "NIWSServerListFilterClassName"); }
可知NFLoadBalancerClassName等是可以配置的
实现IPing:MyPing
package com.segumentfault.spring.cloud.lesson7.user.ribbon.client.ping; import com.netflix.loadbalancer.IPing; import com.netflix.loadbalancer.Server; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.UriComponentsBuilder; import java.net.URI; /** * 实现 {@link IPing} 接口:检查对象 /health 是否正常状态码:200 * */ public class MyPing implements IPing { @Override public boolean isAlive(Server server) { String host = server.getHost(); int port = server.getPort(); // /health endpoint // 通过 Spring 组件来实现URL 拼装 UriComponentsBuilder builder = UriComponentsBuilder.newInstance(); builder.scheme("http"); builder.host(host); builder.port(port); builder.path("/health"); URI uri = builder.build().toUri(); RestTemplate restTemplate = new RestTemplate(); ResponseEntity responseEntity = restTemplate.getForEntity(uri, String.class); // 当响应状态等于 200 时,返回 true ,否则 false return HttpStatus.OK.equals(responseEntity.getStatusCode()); } }
增加配置
application.properties
## 扩展 IPing 实现 user-service-provider.ribbon.NFLoadBalancerPingClassName = \ com.segumentfault.spring.cloud.lesson7.user.ribbon.client.ping.MyPing
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
满满干货,为大数据初学者指点迷津
本人30岁,从学大数据到现在有6年的时间,我谈一下我的经验分享 我自己的经历:刚开始大数据是看书,一页页的看书,因为身边有一个好的资源,有问题可以问我朋友,后来发现看大数据的零基础书籍很难看下去,很多专业的东西对于一个新手根本就看不懂,没有什么效率。(在这里我个人建议,初学不要看书,我的建议是学完一部分后用书去温习,这样很多东西都可以明白,并且可以查缺补漏) 后来是跟着视频学习,那个视频算是经典的,但是现在看的话是多少有些老了,学大数据的时候感觉很多地方根本就不懂,视频上的东西可以看得懂。动手自己做的时候,根本无从下手,那个时候因为年纪小,就想放弃了,但是总是到了第二天早上,又想学了,真的是睡了一觉就好了。 **很多初学者,对大数据的概念都是模糊不清的,大数据是什么,能做什么,学的时候,该按照什么线路去学习,学完往哪方面发展,想深入了解,想学习的同学欢迎加入大数据学习qq群:199427210,有大量干货(零基础以及进阶的经典实战)分享给大家,并且有清华大学毕业的资深大数据讲师给大家免费授课,给大家分享目前国内最完整的大数据高端实战实用学习流程体系** 开始搭建环境,浪费好长时间,百度...
- 下一篇
手把手教你使用TF服务将TensorFlow模型部署到生产环境
介绍 将机器学习(ML)模型应用于生产环境已成为一个火热的的话题,许多框架提供了旨在解决此问题的不同解决方案。为解决这一问题,谷歌发布了TensorFlow(TF)服务,以期待解决将ML模型部署到生产中的问题。 本文提供了一个关于服务于预先训练的卷积语义分割网络的实践教程。阅读本文后,你将能够使用TF服务来部署和向TF训练的深度CNN发出请求等操作。另外,本文将概述TF服务的API及其工作原理。如果你想学习本教程并在计算机上运行示例,请完整了解本文。但是,如果你只想了解TensorFlow服务,你可以专注于前两部分。 TensorFlow服务库-概述 首先我们需要花一些时间来了解TF Serving如何处理ML模型的整个生命周期。在这里,我们将介绍TF服务的主要构建块,本部分的目标是提供TF服务API的介绍。如需深入了解,请访问TF服务文
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- 2048小游戏-低调大师作品
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Red5直播服务器,属于Java语言的直播服务器
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7,8上快速安装Gitea,搭建Git服务器
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7