Nacos 笔记

本文档基于v2.0.3进行整理。

1. Nacos简介

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。(配置中心和注册中心

1.1 主流配置中心对比

目前市面上用的比较多的配置中心有:Spring Cloud Confifig、Apollo、Nacos和Disconf等。 由于Disconf不再维护,下面主要对比一下Spring Cloud Confifig、Apollo和Nacos。

从配置中心角度来看,性能方面Nacos的读写性能最高,Apollo次之,Spring Cloud Confifig依赖Git场景不适合开 放的大规模自动化运维API。功能方面Apollo最为完善,nacos具有Apollo大部分配置管理功能,而Spring Cloud Confifig不带运维管理界面,需要自行开发。Nacos的一大优势是整合了注册中心、配置中心功能,部署和操作相比 Apollo都要直观简单,因此它简化了架构复杂度,并减轻运维及部署工作。

综合来看,Nacos的特点和优势还是比较明显的,下面我们一起进入Nacos的世界。

1.2 主流注册中心对比

目前市面上用的比较多的服务发现中心有:Nacos、Eureka、Consul和Zookeeper。

1.3 Nacos特性

Nacos主要提供以下四大功能:

  1. 服务发现与服务健康检查

    Nacos使服务更容易注册,并通过DNS或HTTP接口发现其他服务,Nacos还提供服务的实时健康检查,以防止向不健康的主机或服务实例发送请求。

  2. 动态配置管理

    动态配置服务允许您在所有环境中以集中和动态的方式管理所有服务的配置。Nacos消除了在更新配置时重新部署应用程序,这使配置的更改更加高效和灵活。

  3. 动态DNS服务

    Nacos提供基于DNS 协议的服务发现能力,旨在支持异构语言的服务发现,支持将注册在Nacos上的服务以域名的方式暴露端点,让三方应用方便的查阅及发现。

  4. 服务和元数据管理

    Nacos 能让您从微服务平台建设的视角管理数据中心的所有服务及元数据,包括管理服务的描述、生命周期、服务的静态依赖分析、服务的健康状态、服务的流量管理、路由及安全策略。

这里动态配置管理的特性说明了Naocs的配置管理能力。

2. 安装启动

安装启动

支持外部 MySQL

单机模式时nacos默认使用嵌入式数据库实现数据的存储,若想使用外部mysql存储nacos数据,需要进行以下步骤:

  • 初始化mysql数据库,新建数据库nacos_confifig,数据库初始化文件:${nacoshome}/conf/nacos-mysql.sql
  • 修改${nacoshome}/conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。
  1. spring.datasource.platform=mysql
  2. db.num=1
  3. db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_config? characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
  4. db.user=nacos_devtest
  5. db.password=youdontknow

注意:支持MySQL 8需要添加插件。

3. 配置管理

3.1 什么是配置中心

什么是配置?

应用程序在启动和运行的时候往往需要读取一些配置信息,配置基本上伴随着应用程序的整个生命周期,比如:数据库连接参数、启动参数等。

配置主要有以下几个特点:

  • 配置是独立于程序的只读变量

    • 配置对于程序是只读的,程序通过读取配置来改变自己的行为,但是程序不应该去改变配置;
  • 配置伴随应用的整个生命周期

    • 配置贯穿于应用的整个生命周期,应用在启动时通过读取配置来初始化,在运行时根据配置调整行为。比如:启动时需要读取服务的端口号、系统在运行过程中需要读取定时策略执行定时任务等。
  • 配置可以有多种加载方式

    • 常见的有程序内部hard code,配置文件,环境变量,启动参数,基于数据库等
  • 配置需要治理

    • 同一份程序在不同的环境(开发,测试,生产)、不同的集群(如不同的数据中心)经常需要有不同的配置,所以需要有完善的环境、集群配置管理

什么是配置中心?

总得来说,配置中心就是一种统一管理各种应用配置的基础服务组件。

在传统巨型单体应用纷纷转向细粒度微服务架构的历史进程中,配置中心是微服务化不可缺少的一个系 统组件,在这种背景下中心化的配置服务即配置中心应运而生,一个合格的配置中心需要满足如下特性:

  • 配置项容易读取和修改
  • 分布式环境下应用配置的可管理性,即提供远程管理配置的能力
  • 支持对配置的修改的检视以把控风险
  • 可以查看配置修改的历史记录
  • 不同部署环境下应用配置的隔离性

3.2 Nacos 配置入门(Spring-Boot形式)

step1:使用Nacos的界面发布配置

step2:通过Nacos API获取配置

  1. /**
  2. * 演示使用Nacos API 对配置中心数据进行增删改查的过程
  3. */
  4. public class NacosApiDemo {
  5. public static void main(String[] args) throws NacosException, InterruptedException {
  6. String serverAddr = "localhost";
  7. String dataId = "application.yml";
  8. String group = "demo";
  9. String nameSpace = "6f97a206-ce19-44c2-85be-c601170d306e";
  10. Properties properties = new Properties();
  11. properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
  12. properties.put(PropertyKeyConst.NAMESPACE, nameSpace);
  13. ConfigService configService = NacosFactory.createConfigService(properties);
  14. // 启动的时候读取配置中心的配置
  15. String content = configService.getConfig(dataId, group, 5000);
  16. System.out.println("配置内容:");
  17. System.out.println(content);
  18. // 监听配置中心数据的变化
  19. configService.addListener(dataId, group, new Listener() {
  20. @Override
  21. public void receiveConfigInfo(String configInfo) {
  22. System.out.println("recieve:" + configInfo);
  23. }
  24. @Override
  25. public Executor getExecutor() {
  26. return null;
  27. }
  28. });
  29. // 向数据中心推送数据,改变原有配置
  30. boolean isPublishOk = configService.publishConfig(dataId, group, "content");
  31. System.out.println(isPublishOk);
  32. //再次读取数据
  33. Thread.sleep(3000);
  34. content = configService.getConfig(dataId, group, 5000);
  35. System.out.println(content);
  36. // 删除配置中心数据
  37. boolean isRemoveOk = configService.removeConfig(dataId, group);
  38. System.out.println(isRemoveOk);
  39. Thread.sleep(3000);
  40. // 再次读书数据
  41. content = configService.getConfig(dataId, group, 5000);
  42. System.out.println(content);
  43. Thread.sleep(300000);
  44. }
  45. }

3.3 Web界面基本使用

Nacos 配置管理模型

对于Nacos配置管理,通过Namespace、group、Data ID能够定位到一个配置集。

配置集(Data ID)

在系统中,一个配置文件通常就是一个配置集,一个配置集可以包含了系统的各种配置信息,例如,一个配置集可 能包含了数据源、线程池、日志级别等配置项。每个配置集都可以定义一个有意义的名称,就是配置集的ID即Data ID。

配置项

配置集中包含的一个个配置内容就是配置项。它代表一个具体的可配置的参数与其值域,通常以 key=value 的形 式存在。例如我们常配置系统的日志输出级别(logLevel=INFO|WARN|ERROR) 就是一个配置项。

配置分组(Group)

配置分组是对配置集进行分组,通过一个有意义的字符串(如 Buy 或 Trade )来表示,不同的配置分组下可以有 相同的配置集(Data ID)。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默 认采用 DEFAULT_GROUP 。配置分组的常见场景:可用于区分不同的项目或应用,例如:学生管理系统的配置集 可以定义一个group为:STUDENT_GROUP。

命名空间(Namespace)

命名空间(namespace)可用于进行不同环境的配置隔离。例如可以隔离开发环境、测试环境和生产环境,因为 它们的配置可能各不相同,或者是隔离不同的用户,不同的开发人员使用同一个nacos管理各自的配置,可通过 namespace隔离。不同的命名空间下,可以存在相同名称的配置分组(Group) 或 配置集。

最佳实践

Nacos抽象定义了Namespace、Group、Data ID的概念,具体这几个概念代表什么,取决于我们把它们看成什 么,这里推荐给大家一种用法,如下图:

命名空间的管理

namespace 的设计是 nacos 基于此做多环境以及多租户(多个用户共同使用nacos)数据(配置和服务)隔离的。

  • 从一个租户(用户)的角度来看,如果有多套不同的环境,那么这个时候可以根据指定的环境来创建不同的 namespce,以此来实现多环境的隔离。例如,你可能有开发,测试和生产三个不同的环境,那么使用一套 nacos 集群可以分别建以下三个不同的 namespace。如下图所示:

  • 从多个租户(用户)的角度来看,每个租户(用户)可能会有自己的 namespace,每个租户(用户)的配置数据以及注 册的服务数据都会归属到自己的 namespace 下,以此来实现多租户间的数据隔离。例如超级管理员分配了三 个租户,分别为张三、李四和王五。分配好了之后,各租户用自己的账户名和密码登录后,创建自己的命名 空间。如下图所示:

Nacos界面使用(配置管理)

上面监听查询的功能说下:可以通过IP地址查询,查询client端已经读取到的配置文件的MD5值,用这个MD5值和配置文件详情中的MD5值对比就可以知道客户端拿到的配置文件是不是最新的。

Spring-Cloud 整合Nacos

将演示如何使用 Spring Cloud Alibaba Nacos ConfifigSpring Cloud应用中集成Nacos,通过 Spring cloud原生方式快捷的获取配置内容。

Spring Cloud是什么:

Spring Cloud是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot 的开发风格做到一键启动和部署。Spring Cloud并没有重复制造轮子,它只是将目前各家公司开发的比较成 熟、经得起实际考验的服务框架组合起来,集成最多的组件要属Netflflix公司,通过Spring Boot风格进行再封 装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发 工具包。

Spring Cloud Alibaba Nacos Confifig是什么:

Spring Cloud Alibaba Nacos Confifig是Spring Cloud Alibaba的子项目,而Spring Cloud Alibaba是阿里巴巴公司提供的开源的基于Spring cloud的微服务套件合集,它致力于提供微服务开发的一站式解决方案,可以理解为spring cloud是一套微服务开发的 标准 ,spring cloud alibaba与spring cloud Netflflix是实现。使用 Spring Cloud Alibaba方案,开发者只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里分布式应用解决方案,通过阿里中间件来迅速搭建分布式应用系统。

step1:添加依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alibaba.cloud</groupId>
  8. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  9. <version>2.2.6.RELEASE</version>
  10. </dependency>
  11. </dependencies>

step2:添加配置(bootstrap.yml)

  1. #日志配置
  2. logging:
  3. config: classpath:logback-app.xml
  4. #Server相关配置
  5. server:
  6. port: ${port:9999}
  7. #Spring相关配置
  8. spring:
  9. application:
  10. name: cloud-app
  11. profiles:
  12. active: @profiles.active@
  13. cloud:
  14. nacos:
  15. config:
  16. server-addr: 127.0.0.1:8848
  17. file-exetension: yaml
  18. namespace: 6f97a206-ce19-44c2-85be-c601170d306e
  19. group: demo

在 Nacos Spring Cloud 中,dataId 的完整格式如下:

  1. ${prefix}-${spring.profiles.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  • spring.profiles.active 即为当前环境对应的 profile,详情可以参考 Spring Boot文档注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 propertiesyaml 类型。

step3:通过 Spring Cloud 原生注解 @RefreshScope 实现配置自动更新

  1. @RestController
  2. @RequestMapping("/config")
  3. @RefreshScope
  4. public class ConfigController {
  5. @Value("${useLocalCache:false}")
  6. private boolean useLocalCache;
  7. @RequestMapping("/get")
  8. public boolean get() {
  9. return useLocalCache;
  10. }
  11. }

自定义配置(data-id)

共享配置文件

  • 团队内部的项目共享配置文件
  1. spring:
  2. application:
  3. name: server1
  4. profiles:
  5. active: @profiles.active@
  6. cloud:
  7. nacos:
  8. config:
  9. server-addr: 127.0.0.2:8848
  10. file-extension: yaml
  11. namespace: 6f97a206-ce19-44c2-85be-c601170d306e
  12. group: demo
  13. # 这边的shared-configs不能配置namespace,和上面的配置共享一个namespace,所以一般用于读取一个团队内部的共享文件
  14. shared-configs[0]:
  15. data-id: common.yaml
  16. refresh: true
  17. group: common
  • 一个项目有多个配置文件的情况
  1. spring:
  2. application:
  3. name: server1
  4. profiles:
  5. active: @profiles.active@
  6. cloud:
  7. nacos:
  8. config:
  9. server-addr: 127.0.0.2:8848
  10. file-extension: yaml
  11. namespace: 6f97a206-ce19-44c2-85be-c601170d306e
  12. group: demo
  13. extensionConfigs[0]:
  14. data-id: jdbc.yaml
  15. refresh: true
  16. group: demo
  17. extensionConfigs[1]:
  18. data-id: o32.yaml
  19. refresh: true
  20. group: demo
  21. shared-configs[0]:
  22. data-id: common.yaml
  23. refresh: true
  24. group: common

配置文件优先级

假如依赖的配置文件有冲突。

主配置文件(通过nacos配置确定的配置文件)> 扩展配置1 > 扩展配置0 > 公共配置

4. 服务发现

微服务环境下,服务经常是多实例部署的。而且经常会增加实例或者下线实例,服务之前怎么互相感知,就是服务发现需要研究的问题。

总结一下,在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无 法使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感知。各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发现中心来获取访问目标服务的网络地址,从而实现服务发现的机制。

4.1 Nacos 服务发现快速入门

采用Feign+Ribbon的整合方式,是由Feign完成远程调用的整个流程。而Feign集成了Ribbon,Feign使用Ribbon

完成调用实例的负载均衡。 (Feign做远程调用,Ribbon用来做负载均衡)

Ribbon 简介

Ribbon是一个客户端负载均衡器,它的责任是从一组实例列表中挑选合适的实例,如何挑选?取决于负载均衡策略

Ribbon核心组件IRule是负载均衡策略接口,它有如下实现:

可通过下面方式在spring boot 配置文件中修改默认的负载均衡策略:

  1. accountservice.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

account-service 是调用的服务的名称,后面的组成部分是固定的。

Feign介绍

Feign是Netflflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。Feign 的英文表意为“假装,伪装,变形”, 可以理解为将HTTP报文请求方式伪装为简单的java接口调用方式。

4.2 服务提供端代码

  1. # Server相关配置
  2. server:
  3. port: 18080
  4. #Spring相关配置
  5. spring:
  6. application:
  7. name: server1
  8. profiles:
  9. active: @profiles.active@
  10. cloud:
  11. nacos:
  12. discovery:
  13. server-addr: 127.0.0.2:8848

依赖:

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alibaba.cloud</groupId>
  8. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  9. </dependency>
  10. </dependencies>

启动服务端:

  1. @SpringBootApplication
  2. @EnableDiscoveryClient
  3. public class CloudServer1 {
  4. private static Logger logger = LoggerFactory.getLogger(CloudServer1.class);
  5. public static void main(String[] args) {
  6. System.setProperty("nacos.logging.default.config.enabled","false");
  7. logger.info("CloudServer1 begin to start...");
  8. SpringApplication.run(CloudServer1.class, args);
  9. logger.info("CloudServer1 start success...");
  10. }
  11. }

4.3 服务调用端代码

step1:添加依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.alibaba.cloud</groupId>
  8. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.springframework.cloud</groupId>
  12. <artifactId>spring-cloud-starter-openfeign</artifactId>
  13. </dependency>
  14. <dependency>
  15. <groupId>com.alibaba.cloud</groupId>
  16. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  17. </dependency>
  18. </dependencies>

step2:添加配置

  1. server:
  2. port: 9999
  3. #Spring相关配置
  4. spring:
  5. application:
  6. name: cloud-comsumer
  7. profiles:
  8. active: @profiles.active@
  9. cloud:
  10. nacos:
  11. discovery:
  12. server-addr: 127.0.0.2:8848

step3:添加客户端调用

  1. @FeignClient(name = "server1")
  2. public interface ServerConsumerClient {
  3. @GetMapping("/echo/chen")
  4. String echoChen();
  5. @GetMapping("/echo/zhao")
  6. String echoZhen();
  7. }

step4:启动应用

  1. @SpringBootApplication
  2. @EnableDiscoveryClient
  3. @EnableFeignClients
  4. public class CloudApp {
  5. private static Logger logger = LoggerFactory.getLogger(CloudApp.class);
  6. public static void main(String[] args) {
  7. System.setProperty("nacos.logging.default.config.enabled","false");
  8. logger.info("app begin to start...");
  9. SpringApplication.run(CloudApp.class, args);
  10. logger.info("app start success...");
  11. }
  12. }

Nacos 使用规范

  • 接入时必须填写用户密码

原理性文章

  • Nacos 客户端读取配置、更新配置、删除配置和监听服务端配置变化的原理;

  • Nacos 各个日志的功能;

  • 配置多个数据库的原理;

  • Nacos 接入用户时必须指定用户密码;

  • Nacos 用户权限管理。 --- https://www.cnblogs.com/yunqishequ/p/12720079.html 对服务发现有没有影响

参考

Nacos 笔记的更多相关文章

  1. Nacos笔记01——使用Nacos作为SpringCloud项目的服务注册中心

    前言 刚学SpringCloud时使用eureka作为服务注册中心,随着网飞公司eureka2.x不再更新,以及最近在公司实习接触到的SpringCloud项目是使用Nacos来做服务注册中心的,所以 ...

  2. Spring Cloud Alibaba学习笔记(22) - Nacos配置管理

    目前业界流行的统一配置管理中心组件有Spring Cloud Config.Spring Cloud Alibaba的Nacos及携程开源的Apollo,本文将介绍Nacos作为统一配置管理中心的使用 ...

  3. Spring Cloud Alibaba学习笔记(2) - Nacos服务发现

    1.什么是Nacos Nacos的官网对这一问题进行了详细的介绍,通俗的来说: Nacos是一个服务发现组件,同时也是一个配置服务器,它解决了两个问题: 1.服务A如何发现服务B 2.管理微服务的配置 ...

  4. nacos 1.1.x 集群部署笔记

    Nacos 是什么? https://nacos.io/zh-cn/docs/what-is-nacos.html 服务(Service)是 Nacos 世界的一等公民.Nacos 支持几乎所有主流类 ...

  5. Nacos学习笔记

    Nacos简介 Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现.服务配置.服务元数据及流量管理.Nacos 帮助更敏捷和容易地构建.交付和管理微服务平台. Nacos 是构建以“服 ...

  6. nacos 使用笔记

    启动命令: 单机模式启动 start.sh -m standalone

  7. SpringBoot开发案例Nacos配置管理中心

    前言 在开发过程中,通常我们会配置一些参数来实现某些功能,比如是否开启某项服务,告警邮件配置等等.一般会通过硬编码.配置文件或者数据库的形式实现. 那么问题来了,如何更加优雅的实现?欢迎来到 Naco ...

  8. 图灵学院JAVA互联网架构师专题学习笔记

    图灵学院JAVA互联网架构师专题学习笔记 下载链接:链接: https://pan.baidu.com/s/1xbxDzmnQudnYtMt5Ce1ONQ 密码: fbdj如果失效联系v:itit11 ...

  9. Spring Cloud Alibaba 初体验(一) Nacos 配置中心

    一.Nacos 下载与初始化配置 本文使用1.2.0,下载地址:https://github.com/alibaba/nacos/releases Nacos 单机模式支持持久化配置到 MySQL 数 ...

随机推荐

  1. 01 JumpServer安装

    1.0.环境说明: 操作系统类型 主机名称 用户及密码 角色 eth0(Vmnet8) eth1(Vmnet1) 防火墙状态 selinux centos7.4 controlnode root:12 ...

  2. 图的存储与遍历C++实现

    1.图的存储 设点数为n,边数为m 1.1.二维数组 方法:使用一个二维数组 adj 来存边,其中 adj[u][v] 为 1 表示存在 u到 v的边,为 0 表示不存在.如果是带边权的图,可以在 a ...

  3. 集合类线程安全吗?ConcurrentModification异常遇到过吗?如何解决?

    集合类不安全的问题 1. ArrayList的线程不安全问题 1.1 首先回顾ArrayList底层 ArrayList的底层数据结构是数组 底层是一个Object[] elementData的数组, ...

  4. FlowNet:simple / correlation 与 相关联操作

    Flow Net : simple / correlation 与 相关联操作 ​ 上一篇文章中(还没来得及写),已经简单的讲解了光流是什么以及光流是如何求得的.同时介绍了几个光流领域的经典传统算法. ...

  5. 官宣.NET 6 预览版4

    我们很高兴发布 .NET 6 Preview 4.我们现在大约完成了 .NET 6 发布的一半.现在是一个很好的时机,可以再次查看.NET6的完整范围.许多功能都接近最终形式,而其他功能将很快推出,因 ...

  6. 链表逆序---python

    class ListNode: Value = '' # 节点要储存的值,因为Python是弱类型,因此无需传入泛型 Next = None # 下一个节点,初始化时为空值 def __init__( ...

  7. Java基础00-多线程28

    1. 实现多线程 1.1 进程 1.2 线程 1.3 多线程的实现方式(方式一:继承Thread类) 代码示例:定义类MyThread: //1:定义一个类MyThread继承Thread类 publ ...

  8. JMeter之Throughput Controller吞吐量控制器

    吞吐量控制器,它是用来控制该控制器下面元件的执行次数,与控制吞吐量的功能无关.(注:用Constant Throughput Timer可以控制吞吐量tps) 作用:控制其子节点的执行次数与负载比例分 ...

  9. ES6 模块export import

    在 ES6 前, 实现模块化使用的是 RequireJS 或者 seaJS(分别是基于 AMD 规范的模块化库, 和基于 CMD 规范的模块化库).ES6 引入了模块化,其设计思想是在编译时就能确定模 ...

  10. airodump-ng的使用及显示

    PWR   表示所接收的信号的强度.表示为负数,数值赿大表示信号赿强.(绝对值赿大,数据赿值小) beacons  表示网卡接收到的AP发出的信号个数