一、建立Eureka Server 端
见 Spring Cloud 进阶之路 — Eureka Server 端从0开始搭建图文教程
二、建立Eureka Client 端
见 Spring Cloud 进阶之路 — 搭建 Eureka Client 并注册至 Eureka Server 注册中心
搭建完成后,在 eureka-client项目中新建 一个 ServerController.java,简单写一个待调用的方法:
@RestController
public class ServerController {
@GetMapping("/getMsg")
public String getMsg(){
return "this is server ";
}
}
启动后,测试可访问,如下图:
三、建立Eureka CallClient 调用端,并使用 RestTemplate 通讯(三种方式)
首先建立Eureka CallClient 调用端应用,启动并测试注册到Eureka 注册中心,如下图:
1、第1种方式(使用RestTemplate 直接获取):
1.1、新建一个 ClientController.java
package com.antma.eurekacallclient.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@Slf4j
public class ClientController {
@GetMapping("/getServerMsg")
public String getServerMsg() {
// 第一种方式,使用RestTemplate 直接获取:
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject("http://localhost:8080/getMsg", String.class);
log.info("result={}", result);
return result;
}
}
1.2、然后访问 localhost:8081/getServerMsg 即返回调用信息,如下图:
2、第2种方式(使用LoadBalancerClient,先通过应用名称得到应用url,再使用RestTemplate):
2.1、 ClientController.java
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("getServerMsg")
public String getServerMsg() {
//第二种方式(使用LoadBalancerClient,先通过应用名称得到应用url,再使用RestTemplate):
RestTemplate restTemplate = new RestTemplate();
ServiceInstance serviceInstance = loadBalancerClient.choose("CLIENT");
String url = String.format("http://%s:%s",serviceInstance.getHost(), serviceInstance.getPort()) + "/getMsg";
System.out.println("url=="+url);
String result = restTemplate.getForObject(url, String.class);
log.info("response2={}", result);
return result;
}
2.2、然后访问 localhost:8081/getServerMsg 即返回调用信息,如下图:
3、第3种方式(先配置RestTemplate,使用@LoadBalanced,直接用restTemplate调用应用名):
3.1、 配置RestTemplate Bean,使用@LoadBalanced注解:
@Component
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
3.2、 ClientController.java
@RestController
@Slf4j
public class ClientController {
@Autowired
RestTemplate restTemplate;
@GetMapping("getServerMsg")
public String getServerMsg() {
//第三种方式(先配置RestTemplate,使用@LoadBalanced,直接用restTemplate调用应用名):
String result = restTemplate.getForObject("http://CLIENT/getMsg", String.class);
log.info("result3={}", result);
return result;
}
}
3.3、然后访问 localhost:8081/getServerMsg 即返回调用信息,如下图:
四、源码查看Ribbon负载均衡配置策略:
在上面第2种方式中,有以下代码:
ServiceInstance serviceInstance = loadBalancerClient.choose("CLIENT");
调用了 loadBalancerClient.choose(String) 方法,实际调用了 RibbonLoadBalancerClient.choose(String)
继续追踪,调用了 getServer(String) -> 调用 getServer(ILoadBalancer) 这里用到了 ILoadBalancer 组件,
这里看到 ILoadBalancer 接口有几个方法,
其中有 chooseServer(选择一个服务),getServerList(已弃用),getAllServers(获取所有服务肯定用的这个方法)
如下图:
然后调用了loadBalancer.chooseServer(String),属 BaseLoadBalancer类,结合官网的配置说明:
这里采用这个配置:
<clientName>.ribbon.NFLoadBalancerRuleClassName: Should implement IRule
配置如下图,并且在子类 DynamicServerListLoadBalancer里打个段点,可以看到负载均衡规则改修改为:RandomRule
负载均衡默认采用的是轮询(RoundRobinRule),在 IRule 组件中,有很多规则,见下图:
在 application.yml 文件中配置所需的规则即可:
CLIENT:
ribbon:
# 负载均衡规则配置
# <clientName>.ribbon.NFLoadBalancerRuleClassName: Should implement IRule
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule