美文网首页
spring-cloud微服务项目实战(3)-ribbon实现客

spring-cloud微服务项目实战(3)-ribbon实现客

作者: 爱编程的凯哥 | 来源:发表于2019-02-09 06:56 被阅读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集成完成

    相关文章

      网友评论

          本文标题:spring-cloud微服务项目实战(3)-ribbon实现客

          本文链接:https://www.haomeiwen.com/subject/oubysqtx.html