spring-cloud微服务项目实战(3)-ribbon实现客
2019-02-09 本文已影响67人
爱编程的凯哥
目标
通过ribbon实现客户端调用服务端api,可根据需求调整负载策略配置
简介
Ribbon是一个客户端的负载均衡器,它提供对大量的HTTP和TCP客户端的访问控制,已实现规则有:
策略名 | 策略声明 | 策略描述 | 实现说明 |
---|---|---|---|
BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。 |
RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 |
开工
-
用老方法创建子moudle:udm-client
image.png
创建一个普通的maven工程,做为工具包,提供公用方法、常量等
创一个工具项目
- 客户端中添加依赖
.....
<dependencies>
<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-ribbon</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>open.template.work</groupId>
<artifactId>commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</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>
......
</project>
添加eureka客户端注解入口
package open.template.work.udm.client;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableEurekaClient
public class UdmClientApplication {
public static void main(String[] args) {
SpringApplication.run(UdmClientApplication.class, args);
}
@Bean
public IRule ribbonRoundRobinRule() {
//轮询策略
return new RoundRobinRule();
}
}
- 配置robin负载规则,如上 配置了一个RoundRobinRule()类,相对应的在application.yml配置对应server采用此策略
spring:
application:
name: udm-client
eureka:
client:
service-url:
defaultZone: http://root:123@peer1:8761/eureka/,http://root:123@peer2:8762/eureka/,http://root:123@peer3:8763/eureka/
server:
port: 80
udm-server:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
- 定义sevice层调用udm-server服务,此处采用LoadBalancerClient的方式实现,并且RestTemplate通过工厂的方式获取,是为了后面做池化,还有共有的一些配置,统一管理,多项目共用。
@Service
public class UdmServerServiceImpl implements UdmServerService {
@Autowired
private LoadBalancerClient loadBalancerClient;
@Override
public String checkServerInfo() {
ServiceInstance instance = loadBalancerClient.choose(CloudServerDirectory.UDM_SERVER);
//测试服务端状态方法
return RestTemplateFactory.getTemplate().getForObject(CloudServerDirectory.getServerUrl(instance.getHost(),instance.getPort())+"hello",String.class);
}
}
对应的CloudServerDirectory.getServerUrl(String ip, int port)方法在commons项目中,后期扩展使用,测试代码如下
public class CloudServerDirectory {
/**
* udm服务端应用名
*/
public static final String UDM_SERVER = "UDM-SERVER";
private static final ConcurrentHashMap<String, String> urlMap = new ConcurrentHashMap<>();
/**
* 根据服务端应用名获取应用url路径,目前只有restful地址
* @param key
* @return
*/
public static String getServerUrl(String key) {
if (!urlMap.contains(key)) {
urlMap.put(key, "http://" + key + "/");
urlMap.get(key);
}
return urlMap.get(key);
}
/**
* 根据服务端应用名获取应用url路径,目前只有restful地址
* @param ip,port
* @return
*/
public static String getServerUrl(String ip,int port) {
String key=ip+port;
if (!urlMap.contains(ip+port)) {
urlMap.put(key,String.format("http://%s:%s/",ip,port));
urlMap.get(key);
}
System.out.println("最终url="+urlMap.get(key));
return urlMap.get(key);
}
}
而restTemplateFactory工厂暂时未加逻辑,防止并发问题,每次暂时new新客户端
public class RestTemplateFactory {
public static RestTemplate getTemplate() {
return new RestTemplate();
}
}
-
好了,启动客户端,此时会看到轮询调用的日志
调用日志
如果想改变负载规则,可以修改new Irule的方法,并且同时修改yml配置文件,注意一个项目中Irule对象只能有一个。
好了,客户端的ribbon集成完成