Ribbon原生api使用

转载自:https://blog.csdn.net/liaokailin/article/details/51362144

  Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将Netflix的中间层服务连接在一起。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。

netflix ribbon的一个简单demo
ribbon.properties配置文件:

# Max number of retries on the same server (excluding the first try)
sample-client.ribbon.MaxAutoRetries=1

# Max number of next servers to retry (excluding the first server)
sample-client.ribbon.MaxAutoRetriesNextServer=1

# Whether all operations can be retried for this client
sample-client.ribbon.OkToRetryOnAllOperations=true

# Interval to refresh the server list from the source
sample-client.ribbon.ServerListRefreshInterval=2000

# Connect timeout used by Apache HttpClient
sample-client.ribbon.ConnectTimeout=3000

# Read timeout used by Apache HttpClient
sample-client.ribbon.ReadTimeout=3000

# Initial list of servers, can be changed via Archaius dynamic property at runtime
sample-client.ribbon.listOfServers=www.u51.xin:80,www.baidu.com:80,www.163.com:80,www.csdn.net:80

RibbonBasicTest:

import com.netflix.client.AbstractLoadBalancerAwareClient;
import com.netflix.client.ClientFactory;
import com.netflix.client.http.HttpRequest;
import com.netflix.client.http.HttpResponse;
import com.netflix.config.ConfigurationManager;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.ZoneAwareLoadBalancer;

import java.net.URI;

public class RibbonBasicTest {
    public static void main(String[] args) throws Exception {
        //加载ribbon配置文件
        ConfigurationManager.loadPropertiesFromResources("ribbon.properties");

        //通过ClientFactory获取指定名称client
        AbstractLoadBalancerAwareClient client = (AbstractLoadBalancerAwareClient) ClientFactory.getNamedClient("sample-client");
        System.out.println("client is " + client.getClass());

        // 获取LoadBalancer
        ILoadBalancer lb = client.getLoadBalancer();
        System.out.println("lb is " + lb.getClass());
        System.out.println("lb stats: " + ((ZoneAwareLoadBalancer) lb).getLoadBalancerStats());
        System.out.println("listOfServers: " + lb.getAllServers());

        //构建请求
        HttpRequest request = HttpRequest.newBuilder().uri(new URI("/")).build();
        for (int i = 0; i < 5; i++) {
            //执行请求, 调用的服务会在listOfServers列表中的数据切换
            HttpResponse response = (HttpResponse) client.executeWithLoadBalancer(request);
            System.out.println("Status code for " + response.getRequestedURI() + ": " + response.getStatus());
        }

        // 修改可用服务列表
        ConfigurationManager.getConfigInstance().setProperty("sample-client.ribbon.listOfServers",
                "www.qq.com:80");
        Thread.sleep(3000);
        for (int i = 0; i < 2; i++) {
            HttpResponse response = (HttpResponse) client.executeWithLoadBalancer(request);
            System.out.println("Status code for " + response.getRequestedURI() + ": " + response.getStatus());
        }
    }
}

运行结果:

client is class com.netflix.niws.client.http.RestClient
lb is class com.netflix.loadbalancer.ZoneAwareLoadBalancer
lb stats: …
listOfServers: [www.u51.xin:80, www.baidu.com:80, www.163.com:80, www.csdn.net:80]
Status code for http://www.baidu.com:80/: 302
Status code for http://www.163.com:80/: 200
Status code for http://www.csdn.net:80/: 301
Status code for http://www.baidu.com:80/: 302
Status code for http://www.163.com:80/: 200
Status code for http://www.qq.com:80/: 200
Status code for http://www.qq.com:80/: 200

  可以发现,默认情况下获取的IClient是RestClient,ILoadBalancer是ZoneAwareLoadBalancer。ZoneAwareLoadBalancer默认使用的ServerList是ConfigurationBasedServerList,也就是从配置中的listOfServers获取服务列表,因此通过修改listOfServers配置可以动态调整服务列表。
  ZoneAwareLoadBalancer的实例化时会调用到BaseLoadBalancer的构造函数,里面设置了负载均衡策略IRule的实现类是RoundRobinRule。在BaseLoadBalancer的chooseServer方法中,调用了IRule中的choose方法来找到一个具体的服务实例。关于各类负载均衡策略之后在介绍。


  如果是非Spring cloud项目,想使用netflix ribbon可以采用上述方式,配置一下已有的服务的列表到listOfServers即可。那如果服务列表已经在Eureka注册了的,那么如何做呢?
  首先,需要有一个EurekaClient,向Eureka发送请求,获取服务列表。其次,ServerList不能是ConfigurationBasedServerList,应该是DiscoveryEnabledNIWSServerList,这个就是从Eureka上获取ServerList。如何来实现呢?

示例
ribbon.properties配置文件:

# Max number of retries on the same server (excluding the first try)
service1.ribbon.MaxAutoRetries=1
service1.ribbon.MaxAutoRetriesNextServer=1
service1.ribbon.OkToRetryOnAllOperations=true
service1.ribbon.ConnectTimeout=3000
service1.ribbon.ReadTimeout=3000
# 每分钟更新service1对应服务的可用地址列表
service1.ribbon.ServerListRefreshInterval=60000
# service1注册在eureka上的服务名称,重要
service1.ribbon.DeploymentContextBasedVipAddresses=COMPUTE-SERVICE
# 指定LoadBalancer使用的ServerList
service1.ribbon.NIWSServerListClassName=com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList
# 指定LoadBalancer使用的负载均衡策略
service1.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

# 控制是否注册自身到eureka中
eureka.registration.enabled=false
eureka.serviceUrl.default=http://localhost:9000/eureka
eureka.region=default
eureka.preferSameZone=true
eureka.shouldUseDns=false

java代码:

public static void useEureka() throws Exception {
    //加载ribbon配置文件
    ConfigurationManager.loadPropertiesFromResources("ribbon.properties");

    // 最关键的代码,加载配置文件,向Eureka发送请求,获取服务列表。
    DiscoveryManager.getInstance().initComponent(
            new MyDataCenterInstanceConfig(),
            new DefaultEurekaClientConfig());

    //ClientFactory.getNamedLoadBalancer会缓存结果, 所以不用担心它每次都会向eureka发起查询
    //参数service1,是ribbon.properties配置文件中配置项的前缀名
    DynamicServerListLoadBalancer lb =
            (DynamicServerListLoadBalancer) ClientFactory.getNamedLoadBalancer("service1");
    System.out.println(lb.getReachableServers());
    System.out.println("choose : " + new RoundRobinRule().choose(lb, null));
}

  这里特别要注意的是配置DeploymentContextBasedVipAddresses,必须是service1服务在Eureka注册的服务名称,不然DiscoveryEnabledNIWSServerList会找不到服务列表。

如果想查看在Eureka的所有服务可以这样:

//加载ribbon配置文件
ConfigurationManager.loadPropertiesFromResources("ribbon.properties");

// 最关键的代码,加载配置文件,向Eureka发送请求,获取服务列表。
DiscoveryManager.getInstance().initComponent(
        new MyDataCenterInstanceConfig(),
        new DefaultEurekaClientConfig());

// 在Eureka上设置为UP
// ApplicationInfoManager.getInstance().setInstanceStatus(InstanceInfo.InstanceStatus.UP);
EurekaClient eurekaClient = DiscoveryManager.getInstance().getEurekaClient();
//获取从Eureka获取的全部的应用列表
Applications apps = eurekaClient.getApplications();
for (Application app: apps.getRegisteredApplications()) {
    System.out.println(app.getName());
    List<String> urls = new ArrayList<>();
    List<InstanceInfo> instances = app.getInstances();
    if (instances.size() > 0) {
        //获取其中一个应用实例,这里可以添加路由算法
        InstanceInfo instance = instances.get(0);
        //获取公开的地址和端口
        urls.add("http://" + instance.getIPAddr() + ":" + instance.getPort());
    }
    System.out.println(urls);
}

猜你喜欢

转载自blog.csdn.net/zero__007/article/details/83715536