ribbon
1.概述
ribbon是一个负载均衡的抽象管理层,主要完成负载均衡的策略管理,规则管理和服务接口管理,资源管理,服务接口在ribbon中是一个抽象接口,在ribbon-eureka中有对应的实现。
2.功能
负载均衡最顶层接口。
/* * * Copyright 2013 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.loadbalancer; import java.util.List; /** * Interface that defines the operations for a software loadbalancer. A typical * loadbalancer minimally need a set of servers to loadbalance for, a method to * mark a particular server to be out of rotation and a call that will choose a * server from the existing list of server. * * @author stonse * */ public interface ILoadBalancer { /** * Initial list of servers. * This API also serves to add additional ones at a later time * The same logical server (host:port) could essentially be added multiple times * (helpful in cases where you want to give more "weightage" perhaps ..) * * @param newServers new servers to add */ public void addServers(List<Server> newServers); /** * Choose a server from load balancer. * * @param key An object that the load balancer may use to determine which server to return. null if * the load balancer does not use this parameter. * @return server chosen */ public Server chooseServer(Object key); /** * To be called by the clients of the load balancer to notify that a Server is down * else, the LB will think its still Alive until the next Ping cycle - potentially * (assuming that the LB Impl does a ping) * * @param server Server to mark as down */ public void markServerDown(Server server); /** * @deprecated 2016-01-20 This method is deprecated in favor of the * cleaner {@link #getReachableServers} (equivalent to availableOnly=true) * and {@link #getAllServers} API (equivalent to availableOnly=false). * * Get the current list of servers. * * @param availableOnly if true, only live and available servers should be returned */ @Deprecated public List<Server> getServerList(boolean availableOnly); /** * @return Only the servers that are up and reachable. */ public List<Server> getReachableServers(); /** * @return All known servers, both reachable and unreachable. */ public List<Server> getAllServers(); }
只有服务的管理和接口的选择,IRule定义了选择方式, 具体的实现类定义了具体的选择方式如随机选择,权重选择等。
package com.netflix.loadbalancer; /** * Interface that defines a "Rule" for a LoadBalancer. A Rule can be thought of * as a Strategy for loadbalacing. Well known loadbalancing strategies include * Round Robin, Response Time based etc. * * @author stonse * */ public interface IRule{ /* * choose one alive server from lb.allServers or * lb.upServers according to key * * @return choosen Server object. NULL is returned if none * server is available */ public Server choose(Object key); public void setLoadBalancer(ILoadBalancer lb); public ILoadBalancer getLoadBalancer(); }
另外ribbon提供了一套将http接口以资源的形式进行管理的方式。
/* * Copyright 2014 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.ribbon; import com.netflix.client.config.ClientConfigFactory; import com.netflix.client.config.IClientConfig; import com.netflix.client.config.IClientConfigKey; import com.netflix.hystrix.HystrixObservableCommand; import com.netflix.ribbon.hystrix.FallbackHandler; public abstract class ResourceGroup<T extends RequestTemplate<?, ?>> { protected final String name; protected final IClientConfig clientConfig; protected final ClientConfigFactory configFactory; protected final RibbonTransportFactory transportFactory; public static abstract class GroupBuilder<T extends ResourceGroup> { public abstract T build(); public abstract GroupBuilder withClientOptions(ClientOptions options); } public static abstract class TemplateBuilder<S, R, T extends RequestTemplate<S, R>> { public abstract TemplateBuilder withFallbackProvider(FallbackHandler<S> fallbackProvider); public abstract TemplateBuilder withResponseValidator(ResponseValidator<R> transformer); /** * Calling this method will enable both Hystrix request cache and supplied external cache providers * on the supplied cache key. Caller can explicitly disable Hystrix request cache by calling * {@link #withHystrixProperties(com.netflix.hystrix.HystrixObservableCommand.Setter)} * * @param cacheKeyTemplate * @return */ public abstract TemplateBuilder withRequestCacheKey(String cacheKeyTemplate); public abstract TemplateBuilder withCacheProvider(String cacheKeyTemplate, CacheProvider<S> cacheProvider); public abstract TemplateBuilder withHystrixProperties(HystrixObservableCommand.Setter setter); public abstract T build(); } protected ResourceGroup(String name) { this(name, ClientOptions.create(), ClientConfigFactory.DEFAULT, RibbonTransportFactory.DEFAULT); } protected ResourceGroup(String name, ClientOptions options, ClientConfigFactory configFactory, RibbonTransportFactory transportFactory) { this.name = name; clientConfig = configFactory.newConfig(); clientConfig.loadProperties(name); if (options != null) { for (IClientConfigKey key: options.getOptions().keySet()) { clientConfig.set(key, options.getOptions().get(key)); } } this.configFactory = configFactory; this.transportFactory = transportFactory; } protected final IClientConfig getClientConfig() { return clientConfig; } public final String name() { return name; } public abstract <S> TemplateBuilder<S, ?, ?> newTemplateBuilder(String name, Class<? extends S> classType); }
3.eureka上实现负载均衡
要在eureka上实现负载均衡执行在eureka的instanceInfo的基础上实现ribbon的Server接口。
/* * * Copyright 2013 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.niws.loadbalancer; import com.netflix.appinfo.InstanceInfo; import com.netflix.appinfo.InstanceInfo.PortType; import com.netflix.loadbalancer.Server; /** * Servers that were obtained via Discovery and hence contain * meta data in the form of InstanceInfo * @author stonse * */ @edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "EQ_DOESNT_OVERRIDE_EQUALS") public class DiscoveryEnabledServer extends Server{ private final InstanceInfo instanceInfo; private final MetaInfo serviceInfo; public DiscoveryEnabledServer(final InstanceInfo instanceInfo, boolean useSecurePort) { this(instanceInfo, useSecurePort, false); } public DiscoveryEnabledServer(final InstanceInfo instanceInfo, boolean useSecurePort, boolean useIpAddr) { super(useIpAddr ? instanceInfo.getIPAddr() : instanceInfo.getHostName(), instanceInfo.getPort()); if(useSecurePort && instanceInfo.isPortEnabled(PortType.SECURE)) super.setPort(instanceInfo.getSecurePort()); this.instanceInfo = instanceInfo; this.serviceInfo = new MetaInfo() { @Override public String getAppName() { return instanceInfo.getAppName(); } @Override public String getServerGroup() { return instanceInfo.getASGName(); } @Override public String getServiceIdForDiscovery() { return instanceInfo.getVIPAddress(); } @Override public String getInstanceId() { return instanceInfo.getId(); } }; } public InstanceInfo getInstanceInfo() { return instanceInfo; } @Override public MetaInfo getMetaInfo() { return serviceInfo; } }