Spring cloud - 负载均衡/服务调用

Ribbon
是一个客户端负载均衡器
LB 负载均衡,平摊用户请求到多个服务上,以达到系统的高可用。

  • 集中式: F5、Nginx,独立于消费方和提供方。
  • 进程式:Ribbon,将负载均衡逻辑集成到消费方,从注册中心获取可用的服务,然后自己选择一个进行访问。

Spring Cloud Netflix默认情况下为 (BeanType beanName:ClassName)提供以下bean:

  • IClientConfig ribbonClientConfig:DefaultClientConfigImpl

  • IRule ribbonRule:ZoneAvoidanceRule

  • IPing ribbonPing:NoOpPing

  • ServerList<Server> ribbonServerList:ConfigurationBasedServerList

  • ServerListFilter<Server> ribbonServerListFilter:ZonePreferenceServerListFilter

  • ILoadBalancer ribbonLoadBalancer:ZoneAwareLoadBalancer

  • ServerListUpdater ribbonServerListUpdater:PollingServerListUpdater

可以自定义修改相关配置:

@Configuration
public class FooConfiguration {
    @Bean
    public IPing ribbonPing(IClientConfig config) {
        return new PingUrl();
    }

    @Bean
    public IRule ribbonRule() {
        return new RetryRule();
    }
}

这里指定了 ping 规则和负载均衡规则。

  • ZoneAvoidanceRule 默认规则,复合判断 server 所在区域的性能和可用性选择。
  • RandomRule 随机
  • RoundRobinRule 轮询
  • WeightedResponseTimeRule 计算平均响应时间去设置权重。刚开始启动收集的数据少,就使用轮询规则。

接下来自定义一个负载均衡规则:
官网例子:

@Configuration
@RibbonClient(name = "foo", configuration = FooConfiguration.class)
public class TestConfiguration {
}

注意:

FooConfiguration必须是@Configuration,但请注意,它不在主应用程序上下文的@ComponentScan中,否则将由所有@RibbonClients共享。如果您使用@ComponentScan(或@SpringBootApplication),则需要采取措施避免包含(例如将其放在一个单独的,不重叠的包中,或者指定要在@ComponentScan)。

public class TimesRule extends AbstractLoadBalancerRule {
    private int times = 5;
    private int total = 0; // 总共被调用的次数
    private int currentIndex = 0; // 当前提供服务的机器号
    
    public TimesRule() {
        super();
    }

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        }
        Server server = null;

        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            List<Server> upList = lb.getReachableServers();
            List<Server> allList = lb.getAllServers();

            int serverCount = allList.size();
            if (serverCount == 0) {
                /*
                 * No servers. End regardless of pass, because subsequent passes only get more
                 * restrictive.
                 */
                return null;
            }

            if (total < times) {
                server = upList.get(currentIndex);
                total++;
            } else {
                total = 0;
                currentIndex++;
                if (currentIndex >= upList.size()) {
                    currentIndex = 0;
                }
            }

            if (server == null) {
                /*
                 * The only time this should happen is if the server list were somehow trimmed.
                 * This is a transient condition. Retry after yielding.
                 */
                Thread.yield();
                continue;
            }

            if (server.isAlive()) {
                return (server);
            }

            // Shouldn't actually happen.. but must be transient or a bug.
            server = null;
            Thread.yield();
        }

        return server;

    }

    @Override
    public Server choose(Object key) {
        return choose(getLoadBalancer(), key);
    }

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }
}

Ribbon + RestTemplate 就是其中一种服务调用的方式。


Feign

Feign是一个声明式的Web服务客户端。使用它就又可以回归面向接口开发,脱离面向 restTemplate 开发。
定义一个接口,加上注解,@FeignClient 绑定服务,@RequestMapping 声明调用的 api 接口,在配置中开启 @EnableFeignClients。

@FeignClient("stores")
public interface StoreClient {
    @RequestMapping(method = RequestMethod.GET, value = "/stores")
    List<Store> getStores();

    @RequestMapping(method = RequestMethod.POST, value = "/stores/{storeId}", consumes = "application/json")
    Store update(@PathVariable("storeId") Long storeId, Store store);
}

Feign 集成了 Ribbon,实现了负载均衡,集成了 Hystrix,实现了服务降级。
与 Ribbon + RestTemplate 不同的是,通过 Feign只需要定义服务绑定接口且以声明的方式控制层调用接口,优雅而简单的实现了服务调用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容