前面几篇文章我们介绍了微服务,知道了微服务网关。下面呢我们就学习一下微服务的注册中心。什么是注册中心呢,现在我们的每个微服务都是部署一个独立的机器或者docker中,每个都有一个独立的IP地址,那么服务发现基本上都是通过某种方式获取到服务所部署的IP地址。A服务调用B服务时如果采用微服务的模式进行调用的话就需要到注册中心获取B服务所部署的机器的ip和端口进而才能进行对B服务的调用。所以可想而知注册中心在整个微服务体系中是十分重要的。我们经常听到的ZooKeeper就是可实现服务发现的组件之一,包括eureka是springcloud体系中提供的服务发现组件。今天我们了解一下nacos以及为什么我们想用nacos取代eureka。
什么是nacos
nacos是阿里开源的可作为服务发现组件和配置中心组件的应用。先看一下nacos架构与生态:
Nacos = Spring Cloud Eureka(注册中心) + Spring Cloud Config(配置中心)
Nacos 可以与 Spring, Spring Boot, Spring Cloud 集成,并能代替 Spring Cloud Eureka, Spring Cloud Config。对应阿里的商业产品对应的就是ACM, EDAS。
- 通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-config 实现配置的动态变更。
- 通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-discovery 实现服务的注册与发现。
nacos的使用
使用Nacos实现服务注册与发现
注册中心在整个微服务体系中的环节与作用,如下图一个简单的流程是服务provider启动向nacos中注册,告知nacos我的IP和端口,之后服务consumer收到nacos对应的同步消息,之后consumer获取provider的所不熟的机器ip和端口进行服务调用。
微服务中ZooKeeper、Eureka、Consul 、Nacos都可以作为注册中心,互相做个对比:
如上图nacos同时支持AP和CP模式,他根据服务注册选择临时和永久来决定走AP模式还是CP模式,他这里支持CP模式我的理解来说,应该是为了配置中心集群,因为nacos可以同时作为注册中心和配置中心,因为他的配置中心信息是保存在nacos里面的,假如因为nacos其中一台挂掉后,还没有同步配置信息,就可能发生配置不一致的情况。Nacos 目前支持临时实例使用心跳上报方式维持活性,发送心跳的周期默认是 5 秒,Nacos 服务端会在 15 秒没收到心跳后将实例设置为不健康,在 30 秒没收到心跳时将这个临时实例摘除。
性能:
Nacos服务发现(3节点)
- 压测容量服务数可达60W,实例注册数达110W,集群运行持续稳定,达到预期;
- 注册/查询实例TPS达到 13000 以上,接口达到预期;
Nacos配置中心 - 发布与监听时间差,在100ms内基本都能监听到配置的更改
nacos配置注册中心流程
(一)下载nacos(https://github.com/alibaba/nacos/releases)下载完成之后,解压。
- Linux/Unix/Mac:sh startup.sh -m standalone
- Windows:cmd startup.cmd -m standalone
startup.sh脚本位于Nacos解压后的bin目录下。这里主要介绍Spring Cloud与Nacos的集成使用。
启动完成之后,访问:http://127.0.0.1:8848/nacos/,可以进入Nacos的服务管理页面,具体如下:
在这插播一句一个小伙伴搞了个公益的nacos服务供大家使用,不知道现在是否还能用了大家可以试试去,以前我用过。
公益Nacos服务:
Nacos控制台
- 地址:http://nacos.didispace.com/nacos/index.html
- 账户与密码均为:nacos
客户端使用配置 - 使用注册中心服务:spring.cloud.nacos.discovery.server-addr=nacos.didispace.com:80
- 使用配置中心服务:spring.cloud.nacos.config.server-addr=nacos.didispace.com:80
(二)构建应用接入Nacos注册中心 - 服务提供端
- 创建一个Spring Boot应用,可以命名为:alibaba-nacos-discovery-server。
- 编辑pom.xml,加入必要的依赖配置。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
此处一定要注意:集成时一定注意版本要求与对应关系
引入包时又springcloud官方和alibaba的,如果用的话尽量保证一种不要混用
如上图,如果使用springboot1.x的,需要使用1.5.0的版本,如果使用时springboot2.x的,需要使用2.0.0以上的版本。
- 启动类上加入@EnableDiscoveryClient注解,并提供一个API接口
@EnableDiscoveryClient
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@GetMapping("/hello1")
public String hello1(@RequestParam String name) {
log.info("name = " + name);
return "hello1: " + name;
}
}
}
- yml或者properties中配置
spring.application.name=alibaba-nacos-discovery-server
server.port=8001
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
- 启动服务在控制台或日志中看到如下内容,代表已经注册成功
INFO 18473 --- [main] o.s.c.a.n.registry.NacosServiceRegistry : nacos registry, alibaba-nacos-discovery-server 10.11.24.69:8001 register finished
之后访问刚才的页面地址则能看到如下:
- 服务消费端
- 创建一个Spring Boot应用,可以命名为:alibaba-nacos-discovery-client-consumer。
- 编辑pom.xml中的依赖内容,跟上边相同.
- 应用主类加上注解并采用LoadBalancerClient进行调用服务接口
@EnableDiscoveryClient
@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/test1")
public String test1() {
// 通过spring cloud common中的负载均衡接口选取服务提供节点实现接口调用
ServiceInstance serviceInstance = loadBalancerClient.choose("alibaba-nacos-discovery-server");
String url = serviceInstance.getUri() + "/hello1?name=" + "lalalala";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);
return "返回结果是 : " + result;
}
}
}
yml配置与服务提供者相同,之后启动消费端我们多次请求test1接口会发现调用服务提供端的ip是不同的也就间接的说明通过LoadBalancerClient接口在获取服务实例的时候,已经实现了对服务提供方实例的负载均衡。
服务之间通信方式
- 使用RestTemplate
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
- 使用WebClient
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
- 使用Feign(推荐)
@FeignClient("alibaba-nacos-discovery-server")
public interface AaService{
@GetMapping("/hello1")
String hello1(@RequestParam(name = "name") String name);
}
需要使用的时候只要在对应的调用处注入AaService 对象,直接调用hello1方法即可。其实不论我们用的是RestTempalte也好、还是用的WebClient也好,还是用的Feign也好,似乎跟我用不用Nacos没啥关系?无论使用Eureka还是Consul,也都是用同样的方法来实现服务调用的,对于Spring Cloud来说,就算我们更换了Nacos作为新的服务注册中心,其实对于我们应用层面的代码是没有影响的。
那么为什么Spring Cloud可以带给我们这样的完美编码体验呢?实际上,这完全归功于Spring Cloud Common的封装,由于在服务注册与发现、客户端负载均衡等方面都做了很好的抽象,而上层应用方面依赖的都是这些抽象接口,而非针对某个具体中间件的实现。所以,在Spring Cloud中,我们可以很方便的去切换服务治理方面的中间件。我们下一篇再继续介绍一下nacos作为另一个功能config的相应配置与坑。大家想了解更多欢迎关注公众号"IT技术小栈”,我在那等你呦~~