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。

开工

  1. 用老方法创建子moudle:udm-client


    image.png

创建一个普通的maven工程,做为工具包,提供公用方法、常量等


创一个工具项目
  1. 客户端中添加依赖
.....

    <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();
    }


}

  1. 配置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
  1. 定义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();
    }
}
  1. 好了,启动客户端,此时会看到轮询调用的日志


    调用日志

如果想改变负载规则,可以修改new Irule的方法,并且同时修改yml配置文件,注意一个项目中Irule对象只能有一个。

好了,客户端的ribbon集成完成

上一篇下一篇

猜你喜欢

热点阅读