前言
本文是根据蚂蚁课堂余胜军老师的课程所做笔记,记录的要点,部分自己的理解可能有所偏差,不当之处会进行修改。
微服务服务治理核心概念
在微服务架构通讯中,服务之间依赖关系非常大,如果通过传统的方式管理服务url地址,一旦地址发生变化,还需要人工修改rpc远程调用地址。
所以采用服务url治理技术,治理的技术可以实现对我们的整个实现动态服务注册与发现,本地负载均衡、容错等。
分布式注册中心实现原理
注册中心实际上就是管理我们服务的url信息,能够实现动态感知。
有Dubbo依赖Zookeeper、Eureka、Consul、Nacos
注册中心就是将一个服务的服务id和其IP与端口号作为键值对存放到注册中心,通过服务id可以找到IP地址和端口号。
另一个服务通过注册中心获取到该服务的ip和端口号后,在本地实现rpc调用。
服务名对应的ip地址是一个列表,通过负载均衡算法取出一个地址调用。
Nacos基本介绍
Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
下载nacos,解压后直接运行bin目录下的start脚本即可
在Linux下使用下面命令代表非集群运行
sh startup.sh -m standalone
默认用8848端口启动,在ip:8848/nacos进入管理面板,默认账号密码都是nacos
服务注册
创建一个会员项目
导入依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba.cloud/spring-cloud-starter-alibaba-nacos-discovery -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
</dependencies>
配置文件
spring:
application:
name: member-nacos #服务名
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 #注册中心地址
创建一个服务
@RestController
public class UserService {
@GetMapping("/user")
public String getUser() {
return "alibaba-nacos-test";
}
}
启动项目
如果使用的是eureka,还需要使用注解@EnableEurekaServer开启服务注册,但是使用nacos,直接启动项目就能注册服务。
使用discoveryClient从注册中心获取接口地址
创建一个订单项目
配置文件与会员项目相同,更改一下端口号。
创建服务调用会员服务
@RestController
public class OrderService {
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("/orderToMember")
public Object orderToMember() {
//通过服务名获取接口地址
List<ServiceInstance> instances = discoveryClient.getInstances("member-nacos");
return instances.get(0);
}
}
使用restTemplate实现RPC远程调用
项目中并没有注册restTemplate,需要手动注册一个。
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
实现调用
@RestController
public class OrderService {
@Autowired
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
@GetMapping("/orderToMember")
public Object orderToMember() {
//通过服务名获取接口地址
List<ServiceInstance> instances = discoveryClient.getInstances("member-nacos");
ServiceInstance serviceInstance = instances.get(0);
//通过服务地址加上方法名调用,String.class为方法返回值类型
String object = restTemplate.getForObject(serviceInstance.getUri() + "/user", String.class);
return "调用返回结果"+object;
}
}
手写负载均衡轮询算法
通常从注册中心获取到的服务是集群列表,使用负载均衡来选择一个服务调用。
负载均衡的算法有:一致性hash计算、轮询、权重、随机
可以用策略模式,来实现不同的算法。这里我们实现轮询算法
创建一个接口
public interface LoadBalancer {
ServiceInstance getOneService(List<ServiceInstance> serviceInstances);
}
实现轮询算法
@Component
public class RotationLoadBalancer implements LoadBalancer {
private AtomicInteger atomicInteger = new AtomicInteger(0);
@Override
public ServiceInstance getOneService(List<ServiceInstance> serviceInstances) {
int index = atomicInteger.incrementAndGet()%serviceInstances.size();
return serviceInstances.get(index);
}
}