Administrator
发布于 2024-01-24 / 2 阅读
0

SpringCloud Netflix Ribbon 实现微服务通信

1.Ribbo增强 RestTemplate

/**
 * 使用 Ribbon 之前的配置, 增强 RestTemplate
 * */
@Component
public class RibbonConfig {

    /**
     * <h2>注入 RestTemplate</h2>
     * */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }


 /**
     * 通过 Ribbon 调用 服务获取 
     * */
    public JwtToken getTokenFromAuthorityServiceByRibbon(
            UsernameAndPassword usernameAndPassword) {

        // 注意到 url 中的 ip 和端口换成了服务名称
	//ribbon 会根据服务id 自动获取host 和 端口
        String requestUrl = String.format(
                "http://%s/接口路径",
                CommonConstant.AUTHORITY_CENTER_SERVICE_ID
        );
        log.info("login request url and body: [{}], [{}]", requestUrl,
                JSON.toJSONString(xxx));

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);

        // 这里一定要使用自己注入的 RestTemplate
        return restTemplate.postForObject(
                requestUrl,
                new HttpEntity<>(JSON.toJSONString(xxx), headers),
                xxx.class  
        );
    }

2.Ribbon 原生API

/**
     * 使用原生的 Ribbon Api, 看看 Ribbon是如何完成: 服务调用 + 负载均衡
     * */
    public JwtToken thinkingInRibbon(UsernameAndPassword usernameAndPassword) {

        String urlFormat = "http://%s/ecommerce-authority-center/authority/token";

        // 1. 找到服务提供方的地址和端口号
        List<ServiceInstance> targetInstances = discoveryClient.getInstances(
                CommonConstant.AUTHORITY_CENTER_SERVICE_ID
        );

        // 构造 Ribbon 服务列表
        List<Server> servers = new ArrayList<>(targetInstances.size());
        targetInstances.forEach(i -> {
            servers.add(new Server(i.getHost(), i.getPort()));
            log.info("found target instance: [{}] -> [{}]", i.getHost(), i.getPort());
        });

        // 2. 使用负载均衡策略实现远端服务调用
        // 构建 Ribbon 负载实例
        BaseLoadBalancer loadBalancer = LoadBalancerBuilder.newBuilder()
                .buildFixedServerListLoadBalancer(servers);
        // 设置负载均衡策略
        loadBalancer.setRule(new RetryRule(new RandomRule(), 300));

        String result = LoadBalancerCommand.builder().withLoadBalancer(loadBalancer)
                .build().submit(server -> {

                    String targetUrl = String.format(
                            urlFormat,
                            String.format("%s:%s", server.getHost(), server.getPort())
                    );
                    log.info("target request url: [{}]", targetUrl);

                    HttpHeaders headers = new HttpHeaders();
                    headers.setContentType(MediaType.APPLICATION_JSON);

                    String tokenStr = new RestTemplate().postForObject(
                            targetUrl,
                            new HttpEntity<>(JSON.toJSONString(usernameAndPassword), headers),
                            String.class
                    );

                    return Observable.just(tokenStr);

                }).toBlocking().first().toString();

        return JSON.parseObject(result, JwtToken.class);
    }