一.Nacos源码搭建

  1. 源码地址:
  2. git clone https://gitee.com/mirrors/Nacos.git
  1. 启动问题1.找不到类
  2. ideal控制台使用:mvn compile
  3. 启动问题2.服务找不到(nacos默认使用集群形式)
  4. -Dnacos.standalone=true

Nacos源码2.0.3一、源码环境搭建以及启动 - 图1
Nacos源码2.0.3一、源码环境搭建以及启动 - 图2

二、nacos2.0.3依赖包

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
  4. <version>2.2.6.RELEASE</version>
  5. <exclusions>
  6. <exclusion>
  7. <groupId>com.alibaba.nacos</groupId>
  8. <artifactId>nacos-client</artifactId>
  9. </exclusion>
  10. </exclusions>
  11. </dependency>
  12. <dependency>
  13. <groupId>com.alibaba.cloud</groupId>
  14. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  15. <version>2.2.6.RELEASE</version>
  16. <exclusions>
  17. <exclusion>
  18. <groupId>com.alibaba.nacos</groupId>
  19. <artifactId>nacos-client</artifactId>
  20. </exclusion>
  21. </exclusions>
  22. </dependency>
  23. <dependency>
  24. <groupId>com.alibaba.nacos</groupId>
  25. <artifactId>nacos-client</artifactId>
  26. </dependency>
  27. <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
  28. <dependency>
  29. <groupId>org.springframework.boot</groupId>
  30. <artifactId>spring-boot-starter-web</artifactId>
  31. </dependency>
  32. <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
  33. <dependency>
  34. <groupId>org.projectlombok</groupId>
  35. <artifactId>lombok</artifactId>
  36. </dependency>

二. Nacos启动注入类

NacosDiscoveryClientConfiguration

  1. @Configuration(
  2. proxyBeanMethods = false
  3. )
  4. @ConditionalOnDiscoveryEnabled
  5. @ConditionalOnBlockingDiscoveryEnabled
  6. @ConditionalOnNacosDiscoveryEnabled
  7. @AutoConfigureBefore({SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class})
  8. @AutoConfigureAfter({NacosDiscoveryAutoConfiguration.class})
  9. public class NacosDiscoveryClientConfiguration {
  10. public NacosDiscoveryClientConfiguration() {
  11. }
  12. @Bean
  13. public DiscoveryClient nacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
  14. return new NacosDiscoveryClient(nacosServiceDiscovery);
  15. }
  16. @Bean
  17. @ConditionalOnMissingBean
  18. @ConditionalOnProperty(
  19. value = {"spring.cloud.nacos.discovery.watch.enabled"},
  20. matchIfMissing = true
  21. )
  22. public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties nacosDiscoveryProperties) {
  23. return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties);
  24. }
  25. }

NacosDiscoveryClient

  1. public class NacosDiscoveryClient implements DiscoveryClient {
  2. private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class);
  3. public static final String DESCRIPTION = "Spring Cloud Nacos Discovery Client";
  4. private NacosServiceDiscovery serviceDiscovery;
  5. public NacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
  6. this.serviceDiscovery = nacosServiceDiscovery;
  7. }
  8. }

NacosWatch

  1. 观察者
  2. 创建定时任务线程池(Nacos-Watch-Task-Scheduler),默认有一个线程,使用AbortPolicy拒绝策略
  1. public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle {
  2. private static final Logger log = LoggerFactory.getLogger(NacosWatch.class);
  3. private Map<String, EventListener> listenerMap = new ConcurrentHashMap(16);
  4. private final AtomicBoolean running = new AtomicBoolean(false);
  5. private final AtomicLong nacosWatchIndex = new AtomicLong(0L);
  6. private ApplicationEventPublisher publisher;
  7. private ScheduledFuture<?> watchFuture;
  8. private NacosServiceManager nacosServiceManager;
  9. private final NacosDiscoveryProperties properties;
  10. private final ThreadPoolTaskScheduler taskScheduler;
  11. public NacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties) {
  12. this.nacosServiceManager = nacosServiceManager;
  13. this.properties = properties;
  14. this.taskScheduler = getTaskScheduler();
  15. }
  16. private static ThreadPoolTaskScheduler getTaskScheduler() {
  17. ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
  18. taskScheduler.setBeanName("Nacos-Watch-Task-Scheduler");
  19. taskScheduler.initialize();
  20. return taskScheduler;
  21. }
  22. public void initialize() {
  23. if (this.logger.isInfoEnabled()) {
  24. this.logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
  25. }
  26. if (!this.threadNamePrefixSet && this.beanName != null) {
  27. this.setThreadNamePrefix(this.beanName + "-");
  28. }
  29. #使用AbortPolicy策略:丢弃任务并抛出RejectedExecutionException异常
  30. this.executor = this.initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
  31. }
  32. }

NacosDiscoveryAutoConfiguration

  1. @Configuration
  2. @EnableConfigurationProperties
  3. @ConditionalOnNacosDiscoveryEnabled
  4. @ConditionalOnProperty(
  5. value = {"spring.cloud.service-registry.auto-registration.enabled"},
  6. matchIfMissing = true
  7. )
  8. @AutoConfigureAfter({AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class})
  9. public class NacosDiscoveryAutoConfiguration {
  10. public NacosDiscoveryAutoConfiguration() {
  11. }
  12. @Bean
  13. public NacosServiceRegistry nacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
  14. return new NacosServiceRegistry(nacosDiscoveryProperties);
  15. }
  16. @Bean
  17. @ConditionalOnBean({AutoServiceRegistrationProperties.class})
  18. public NacosRegistration nacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties, ApplicationContext context) {
  19. return new NacosRegistration(nacosDiscoveryProperties, context);
  20. }
  21. @Bean
  22. @ConditionalOnBean({AutoServiceRegistrationProperties.class})
  23. public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {
  24. return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
  25. }
  26. }

NacosRegistration

  1. public class NacosRegistration implements Registration, ServiceInstance {
  2. public static final String MANAGEMENT_PORT = "management.port";
  3. public static final String MANAGEMENT_CONTEXT_PATH = "management.context-path";
  4. public static final String MANAGEMENT_ADDRESS = "management.address";
  5. public static final String MANAGEMENT_ENDPOINT_BASE_PATH = "management.endpoints.web.base-path";
  6. private NacosDiscoveryProperties nacosDiscoveryProperties;
  7. private ApplicationContext context;
  8. public NacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties, ApplicationContext context) {
  9. this.nacosDiscoveryProperties = nacosDiscoveryProperties;
  10. this.context = context;
  11. }
  12. @PostConstruct
  13. public void init() {
  14. Map<String, String> metadata = this.nacosDiscoveryProperties.getMetadata();
  15. Environment env = this.context.getEnvironment();
  16. String endpointBasePath = env.getProperty("management.endpoints.web.base-path");
  17. if (!StringUtils.isEmpty(endpointBasePath)) {
  18. metadata.put("management.endpoints.web.base-path", endpointBasePath);
  19. }
  20. Integer managementPort = ManagementServerPortUtils.getPort(this.context);
  21. if (null != managementPort) {
  22. metadata.put("management.port", managementPort.toString());
  23. String contextPath = env.getProperty("management.server.servlet.context-path");
  24. String address = env.getProperty("management.server.address");
  25. if (!StringUtils.isEmpty(contextPath)) {
  26. metadata.put("management.context-path", contextPath);
  27. }
  28. if (!StringUtils.isEmpty(address)) {
  29. metadata.put("management.address", address);
  30. }
  31. }
  32. if (null != this.nacosDiscoveryProperties.getHeartBeatInterval()) {
  33. metadata.put("preserved.heart.beat.interval", this.nacosDiscoveryProperties.getHeartBeatInterval().toString());
  34. }
  35. if (null != this.nacosDiscoveryProperties.getHeartBeatTimeout()) {
  36. metadata.put("preserved.heart.beat.timeout", this.nacosDiscoveryProperties.getHeartBeatTimeout().toString());
  37. }
  38. if (null != this.nacosDiscoveryProperties.getIpDeleteTimeout()) {
  39. metadata.put("preserved.ip.delete.timeout", this.nacosDiscoveryProperties.getIpDeleteTimeout().toString());
  40. }
  41. }
  42. }

NacosServiceRegistry

  1. public class NacosServiceRegistry implements ServiceRegistry<Registration> {
  2. private static final Logger log = LoggerFactory.getLogger(NacosServiceRegistry.class);
  3. private final NacosDiscoveryProperties nacosDiscoveryProperties;
  4. private final NamingService namingService;
  5. public NacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
  6. this.nacosDiscoveryProperties = nacosDiscoveryProperties;
  7. #这里会将namingService 注册进容器
  8. this.namingService = nacosDiscoveryProperties.namingServiceInstance();
  9. }
  10. public NamingService namingServiceInstance() {
  11. if (null != this.namingService) {
  12. return this.namingService;
  13. } else {
  14. try {
  15. #这里通过构造器反射获取实例
  16. this.namingService = NacosFactory.createNamingService(this.getNacosProperties());
  17. } catch (Exception var2) {
  18. log.error("create naming service error!properties={},e=,", this, var2);
  19. return null;
  20. }
  21. return this.namingService;
  22. }
  23. }
  24. }

NacosNamingService

  1. public class NacosNamingService implements NamingService {
  2. private static final String DEFAULT_PORT = "8080";
  3. private static final long DEFAULT_HEART_BEAT_INTERVAL;
  4. private String namespace;
  5. private String endpoint;
  6. private String serverList;
  7. private String cacheDir;
  8. private String logName;
  9. private HostReactor hostReactor;
  10. private BeatReactor beatReactor;
  11. private EventDispatcher eventDispatcher;
  12. private NamingProxy serverProxy;
  13. public NacosNamingService(String serverList) {
  14. Properties properties = new Properties();
  15. properties.setProperty("serverAddr", serverList);
  16. this.init(properties);
  17. }
  18. public NacosNamingService(Properties properties) {
  19. this.init(properties);
  20. }
  21. private void init(Properties properties) {
  22. this.namespace = InitUtils.initNamespaceForNaming(properties);
  23. this.initServerAddr(properties);
  24. InitUtils.initWebRootContext();
  25. this.initCacheDir();
  26. this.initLogName(properties);
  27. this.eventDispatcher = new EventDispatcher();
  28. this.serverProxy = new NamingProxy(this.namespace, this.endpoint, this.serverList);
  29. this.serverProxy.setProperties(properties);
  30. this.beatReactor = new BeatReactor(this.serverProxy, this.initClientBeatThreadCount(properties));
  31. this.hostReactor = new HostReactor(this.eventDispatcher, this.serverProxy, this.cacheDir, this.isLoadCacheAtStart(properties), this.initPollingThreadCount(properties));
  32. }
  33. private int initClientBeatThreadCount(Properties properties) {
  34. return properties == null ? UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT : NumberUtils.toInt(properties.getProperty("namingClientBeatThreadCount"), UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
  35. }
  36. }

NacosDiscoveryProperties

  1. @ConfigurationProperties("spring.cloud.nacos.discovery")
  2. public class NacosDiscoveryProperties {
  3. private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryProperties.class);
  4. private String serverAddr;
  5. private String endpoint; # 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
  6. private String namespace;
  7. private long watchDelay = 30000L;
  8. private String logName;# 日志文件名
  9. @Value("${spring.cloud.nacos.discovery.service:${spring.application.name:}}")
  10. private String service;
  11. private float weight = 1.0F;#取值范围 1 100,数值越大,权重越大
  12. private String clusterName = "DEFAULT";
  13. private String namingLoadCacheAtStart = "false";
  14. private Map<String, String> metadata = new HashMap();#使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
  15. private boolean registerEnabled = true;
  16. private String ip;# 优先级最高
  17. private String networkInterface = "";#当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址
  18. private int port = -1;# 默认情况下不用配置,会自动探测
  19. private boolean secure = false;
  20. private String accessKey;# 当要上阿里云时,阿里云上面的一个云账号名
  21. private String secretKey;# 当要上阿里云时,阿里云上面的一个云账号密码
  22. private Integer heartBeatInterval;
  23. private Integer heartBeatTimeout;
  24. private Integer ipDeleteTimeout;
  25. @Autowired
  26. private InetUtils inetUtils;
  27. @Autowired
  28. private Environment environment;
  29. private NamingService namingService;
  30. private NamingMaintainService namingMaintainService;
  31. public NacosDiscoveryProperties() {
  32. }
  33. @PostConstruct
  34. public void init() throws SocketException {
  35. this.metadata.put("preserved.register.source", "SPRING_CLOUD");
  36. if (this.secure) {
  37. this.metadata.put("secure", "true");
  38. }
  39. this.serverAddr = Objects.toString(this.serverAddr, "");
  40. if (this.serverAddr.lastIndexOf("/") != -1) {
  41. this.serverAddr = this.serverAddr.substring(0, this.serverAddr.length() - 1);
  42. }
  43. this.endpoint = Objects.toString(this.endpoint, "");
  44. this.namespace = Objects.toString(this.namespace, "");
  45. this.logName = Objects.toString(this.logName, "");
  46. if (StringUtils.isEmpty(this.ip)) {
  47. if (StringUtils.isEmpty(this.networkInterface)) {
  48. this.ip = this.inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
  49. } else {
  50. NetworkInterface netInterface = NetworkInterface.getByName(this.networkInterface);
  51. if (null == netInterface) {
  52. throw new IllegalArgumentException("no such interface " + this.networkInterface);
  53. }
  54. Enumeration inetAddress = netInterface.getInetAddresses();
  55. while(inetAddress.hasMoreElements()) {
  56. InetAddress currentAddress = (InetAddress)inetAddress.nextElement();
  57. if (currentAddress instanceof Inet4Address && !currentAddress.isLoopbackAddress()) {
  58. this.ip = currentAddress.getHostAddress();
  59. break;
  60. }
  61. }
  62. if (StringUtils.isEmpty(this.ip)) {
  63. throw new RuntimeException("cannot find available ip from network interface " + this.networkInterface);
  64. }
  65. }
  66. }
  67. this.overrideFromEnv(this.environment);
  68. }
  69. }