项目结构
主项目maven依赖
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ```
org.springframework.boot spring-boot-starter-parent 2.0.0.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-alibaba-nacos-discovery 0.2.2.RELEASE
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
### [](#%E4%BC%9A%E5%91%98%E6%9C%8D%E5%8A%A1-%E7%94%9F%E4%BA%A7%E8%80%85 "会员服务(生产者)")会员服务(生产者)
##### [](#%E6%9C%8D%E5%8A%A1%E6%8E%A5%E5%8F%A3 "服务接口")服务接口
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
``` | ```
@RestController public class MemberService { @Value("${server.port}") private String serverPort; /** * 会员服务提供的接口 * * @param userId * @return */ @RequestMapping("/getUser") public String getUser(Integer userId) { return "hello nacos,端口号:" + serverPort; } }
``` |
| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
##### [](#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6 "配置文件")配置文件
| ```
1 2 3 4 5 6 7 8 9 10
``` | ```
spring: application: name: tinner-member cloud: nacos: discovery: #nacos注册地址 server-addr: 127.0.0.1:8848 server: port: 8081
``` |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
**注意:**\
在这里我直接使用负载均衡进行调用了,所以要启动两个服务来模拟实现集群(修改端口号),关于idea中支持一套代码启动两个服务的设置:

### [](#%E8%AE%A2%E5%8D%95%E6%9C%8D%E5%8A%A1-%E6%B6%88%E8%B4%B9%E8%80%85 "订单服务(消费者)")订单服务(消费者)
##### [](#%E8%AE%A2%E5%8D%95%E8%B0%83%E7%94%A8%E4%BC%9A%E5%91%98%E6%9C%8D%E5%8A%A1 "订单调用会员服务")订单调用会员服务
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
``` | ```
/** * @Classname OrderController * @Description * @Date 2020/8/5 3:44 下午 * @Created by jinping */ @RestController public class OrderController { @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @Autowired private LoadBalancer loadBalancer; @GetMapping("/orderToMember") public Object orderToMember(){ //1.根据服务名称从注册中心获取到集群的列表地址 List<ServiceInstance> instances = discoveryClient.getInstances("tinner-member"); //2.列表任意选择一个,实现本地rpc调用 rest // ServiceInstance serviceInstance = instances.get(0); ServiceInstance singleAddress = loadBalancer.getSingleAddress(instances); String result = restTemplate.getForObject(singleAddress.getUri() + "/getUser", String.class); return "订单调用会员返回结果:"+ result; } }
``` |
| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
##### [](#%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%AE%97%E6%B3%95 "负载均衡算法")负载均衡算法
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
``` | ```
/** * @Classname LoadBalancer * @Description * @Date 2020/8/5 4:19 下午 * @Created by jinping */ public interface LoadBalancer { /** * 根据多个不同的地址,返回单个调用rpc地址 * @param serviceInstanceList * @return */ ServiceInstance getSingleAddress(List<ServiceInstance> serviceInstanceList); }
``` |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ```
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
``` | ```
/** * @Classname RotationLoadBalancer * @Description 轮询的方式进行负载均衡 * @Date 2020/8/5 4:29 下午 * @Created by jinping */ @Component public class RotationLoadBalancer implements LoadBalancer { //访问次数 private AtomicInteger requireNum = new AtomicInteger(0); /** * 轮询的方式 * @param serviceInstanceList * @return */ @Override public ServiceInstance getSingleAddress(List<ServiceInstance> serviceInstanceList) { return serviceInstanceList.get(requireNum.incrementAndGet() % serviceInstanceList.size()); } }
``` |
| -------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
### [](#%E8%BF%90%E8%A1%8C%E6%95%88%E6%9E%9C "运行效果")运行效果
1、分别以8080、8081端口启动两个tinner-member服务,可以看到在nacos控制台中注册了两个`tinner-member`服务

\
2、启动order服务,调用order的接口,多次调用,可以依次看到轮询访问 `tinner-member`服务


\
3、如果在控制台中将某个节点下掉,由于轮询的时候是动态获取服务列表的,所以对于调用方并没有感知,依旧能为order提供服务
