`

Ribbon 和 Eureka 的集成

    博客分类:
  • java
阅读更多

Ribbon 是 Netflix 发布的云中间层服务开源项目,其主要功能是提供客户侧软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Eureka 是一个 RESTful 服务,用来定位运行在 AWS 域(Region)中的中间层服务。本文介绍 Eureka 和 Ribbon 的集成,附带 Ribbon 自定义负载均衡算法示例。
        Ribbon 和 Eureka 的集成,其实也就是让 Ribbon 充当 Eureka 架构中的 Application Client 角色。本文示例基于前边相关博客中的 demo 而写。阅读本文最好参考一下《云中间层服务 - 区域感知负载均衡器 Ribbon》、《Eureka 的 Application Client 客户端的运行示例》。
        Why Eureka need Ribbon?
        Eureka 附带客户端库,为何还要 Ribbon 呢?
        Ribbon 的负载均衡算法、区域感知负载均衡器久经考验,可以直接拿来使用。
        Why Ribbon need Eureka?
        熟悉 Ribbon 的同学都知道,Ribbon 维护了一个服务器列表,如果服务器有宕机现象,Ribbon 能够自行将其剔除;但如果该服务器故障排除,重新启动,或者增加新的负载节点,我们需要手工调用 Ribbon 的接口将其动态添加进 Ribbon 的服务器列表。这样明显不够尽如人意。如何能够在服务节点启动时,自行添加服务列表?—— Eureka。Eureka 提供了 Application Service 客户端的自行注册的功能。此外,Eureka 的缓存机制能够防止大规模宕机带来的灾难性后果。
        下面开始我们的集成。进行以下操作之前,请确保 Eureka Server 已启动,Eureka Application Service 客户端已注册到 Server(参考《Eureka 的 Application Client 客户端的运行示例》)。
        1. 加入 ribbon-eureka 依赖包
        http://mvnrepository.com/artifact/com.netflix.ribbon/ribbon-eureka 选择合适的版本下载,作者下载的是 ribbon-eureka-0.3.12.jar。
        2. 配置的初始化

        配置文件基本采用《Eureka 的 Application Client 客户端的运行示例》Eureka Application Client 客户端配置。另外增添以下配置项:

    启用客户端负载均衡器并将其配置为 DynamicServerListLoadBalancer 或其子类(这个无须在配置中体现,因为这个是 Eureka 和 Ribbon 集成默认为 true 的)。
    将 ServerList 配置为 com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList。
    配置服务器(负载均衡节点)的刷新频率(可选。默认是为 30 秒)。
    为 Eureka 客户端配置服务器的虚拟地址(VIP 地址),并确保这个地址匹配到服务器(Application Service)注册 Eureka Server 时所用到的那个。

        总之就是在《Eureka 的 Application Client 客户端的运行示例》基础上添加了以下配置项:
[plain] view plain copy print?

    myclient.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList 
     
     
    # refresh every minute  
    myclient.ribbon.ServerListRefreshInterval=60000 
     
     
    # movieservice is the virtual address that the target server(s) uses to register with Eureka server 
    myclient.ribbon.DeploymentContextBasedVipAddresses=movieservice 
            配置文件的初始化仍然采用《Eureka 的 Application Client 客户端的运行示例》中的配置初始化方法: 
            // Register with Eureka 
            DiscoveryManager.getInstance().initComponent( 
                    new MyDataCenterInstanceConfig(), 
                    new DefaultEurekaClientConfig()); 
            ApplicationInfoManager.getInstance().setInstanceStatus( 
                    InstanceStatus.UP); 


        3. 自定义负载均衡算法
        负载均衡算法,简单 demo 起见,使用随机算法,就用 ribbon-core 类库里的 com.netflix.loadbalancer.RandomRule 所提供的随机负载算法,拿到侍服主机:
[java] view plain copy print?

    // get LoadBalancer instance from configuration, properties file 
    DynamicServerListLoadBalancer lb = (DynamicServerListLoadBalancer) ClientFactory.getNamedLoadBalancer("myclient"); 
    // use RandomRule 's RandomRule algorithm to get a random server from lb 's server list 
    RandomRule randomRule = new RandomRule(); 
    Server randomAlgorithmServer = randomRule.choose(lb, null); 
    logger.debug("random algorithm server host:" + randomAlgorithmServer.getHost() + ";port:" + randomAlgorithmServer.getPort()); 


        4. Application Client 网络请求
        请求代码和《Eureka 的 Application Client 客户端的运行示例》中的一般无二,在此不再赘述。
        5. Application Client 关闭时取消注册
        取消代码和《Eureka 的 Application Client 客户端的运行示例》中的一般无二,在此不再赘述。
        6. 运行 demo
        新建一个项目(不要和 Application Service 的 demo 跑在同一个项目下),现在我们把完整的 Eureka Application Client 和 Ribbon Client 集成的代码整理一下。
[java] view plain copy print?

    /*
     * Copyright 2012 Netflix, Inc.
     *
     *    Licensed under the Apache License, Version 2.0 (the "License");
     *    you may not use this file except in compliance with the License.
     *    You may obtain a copy of the License at
     *
     *        http://www.apache.org/licenses/LICENSE-2.0
     *
     *    Unless required by applicable law or agreed to in writing, software
     *    distributed under the License is distributed on an "AS IS" BASIS,
     *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     *    See the License for the specific language governing permissions and
     *    limitations under the License.
     */ 
     
     
    package com.netflix.eureka; 
     
     
    import java.io.BufferedReader; 
    import java.io.IOException; 
    import java.io.InputStreamReader; 
    import java.io.PrintStream; 
    import java.net.InetSocketAddress; 
    import java.net.Socket; 
    import java.util.Date; 
    import java.util.Iterator; 
    import java.util.List; 
     
     
    import org.slf4j.Logger; 
    import org.slf4j.LoggerFactory; 
     
     
    import com.netflix.appinfo.ApplicationInfoManager; 
    import com.netflix.appinfo.InstanceInfo.InstanceStatus; 
    import com.netflix.appinfo.MyDataCenterInstanceConfig; 
    import com.netflix.client.ClientFactory; 
    import com.netflix.discovery.DefaultEurekaClientConfig; 
    import com.netflix.discovery.DiscoveryManager; 
    import com.netflix.loadbalancer.DynamicServerListLoadBalancer; 
    import com.netflix.loadbalancer.RandomRule; 
    import com.netflix.loadbalancer.Server; 
     
     
    /**
     * Sample Eureka client that discovers the service using Eureka and sends
     * requests.
     *
     * @author Karthik Ranganathan
     *
     */ 
    public class SampleEurekaRibbonClient { 
        private static final Logger logger = LoggerFactory 
                .getLogger(SampleEurekaRibbonClient.class); 
     
     
        public void sendRequestToServiceUsingEureka() { 
     
     
            // Register with Eureka 
            DiscoveryManager.getInstance().initComponent( 
                    new MyDataCenterInstanceConfig(), 
                    new DefaultEurekaClientConfig()); 
            ApplicationInfoManager.getInstance().setInstanceStatus( 
                    InstanceStatus.UP); 
            // get LoadBalancer instance from configuration, properties file 
            DynamicServerListLoadBalancer lb = (DynamicServerListLoadBalancer) ClientFactory.getNamedLoadBalancer("myclient"); 
            // show all servers in the list 
            List<Server> list = lb.getServerList(false); 
            Iterator<Server> it = list.iterator(); 
            while (it.hasNext()) { 
                Server server = it.next(); 
                logger.debug("application service host:" + server.getHost() + ";port=" + server.getPort()); 
            } 
            // use RandomRule 's RandomRule algorithm to get a random server from lb 's server list 
            RandomRule randomRule = new RandomRule(); 
            Server randomAlgorithmServer = randomRule.choose(lb, null); 
            logger.debug("random algorithm server host:" + randomAlgorithmServer.getHost() + ";port:" + randomAlgorithmServer.getPort()); 
            // communicate with the server 
            Socket s = new Socket(); 
            try { 
                s.connect(new InetSocketAddress(randomAlgorithmServer.getHost(), randomAlgorithmServer.getPort())); 
            } catch (IOException e) { 
                logger.error("Could not connect to the server :" 
                        + randomAlgorithmServer.getHost() + " at port " + randomAlgorithmServer.getPort()); 
            } 
            try { 
                logger.debug("Connected to server. Sending a sample request"); 
                PrintStream out = new PrintStream(s.getOutputStream()); 
                out.println("Sample request " + new Date()); 
                String str = null; 
                logger.debug("Waiting for server response.."); 
                BufferedReader rd = new BufferedReader(new InputStreamReader( 
                        s.getInputStream())); 
                str = rd.readLine(); 
                if (str != null) { 
                    logger.debug("Received response from server. Communication all fine using Eureka :"); 
                    logger.debug("Exiting the client. Demo over.."); 
                } 
                rd.close(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
                logger.error(e.getMessage(), e); 
            } 
            this.unRegisterWithEureka(); 
        } 
     
     
        public void unRegisterWithEureka() { 
            // Un register from eureka. 
            DiscoveryManager.getInstance().shutdownComponent(); 
        } 
     
     
        public static void main(String[] args) { 
            SampleEurekaRibbonClient sampleEurekaRibbonClient = new SampleEurekaRibbonClient(); 
            sampleEurekaRibbonClient.sendRequestToServiceUsingEureka(); 
     
     
        } 
    } 


        之后是把配置文件、log4j 文件整理一下,运行 SampleEurekaRibbonClient,日志显示 demo 成功。
        参考资料

    https://github.com/Netflix/ribbon/wiki/Programmers-Guide

本文来源:http://blog.csdn.net/defonds/article/details/38016301

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics