一.Nacos源码搭建
源码地址:
git clone https://gitee.com/mirrors/Nacos.git
启动问题1.找不到类
在ideal控制台使用:mvn compile
启动问题2.服务找不到(nacos默认使用集群形式)
-Dnacos.standalone=true
二、nacos2.0.3依赖包
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.2.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.6.RELEASE</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
二. Nacos启动注入类
NacosDiscoveryClientConfiguration
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnDiscoveryEnabled
@ConditionalOnBlockingDiscoveryEnabled
@ConditionalOnNacosDiscoveryEnabled
@AutoConfigureBefore({SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class})
@AutoConfigureAfter({NacosDiscoveryAutoConfiguration.class})
public class NacosDiscoveryClientConfiguration {
public NacosDiscoveryClientConfiguration() {
}
@Bean
public DiscoveryClient nacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
return new NacosDiscoveryClient(nacosServiceDiscovery);
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(
value = {"spring.cloud.nacos.discovery.watch.enabled"},
matchIfMissing = true
)
public NacosWatch nacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosWatch(nacosServiceManager, nacosDiscoveryProperties);
}
}
NacosDiscoveryClient
public class NacosDiscoveryClient implements DiscoveryClient {
private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryClient.class);
public static final String DESCRIPTION = "Spring Cloud Nacos Discovery Client";
private NacosServiceDiscovery serviceDiscovery;
public NacosDiscoveryClient(NacosServiceDiscovery nacosServiceDiscovery) {
this.serviceDiscovery = nacosServiceDiscovery;
}
}
NacosWatch
观察者
创建定时任务线程池(Nacos-Watch-Task-Scheduler),默认有一个线程,使用AbortPolicy拒绝策略
public class NacosWatch implements ApplicationEventPublisherAware, SmartLifecycle {
private static final Logger log = LoggerFactory.getLogger(NacosWatch.class);
private Map<String, EventListener> listenerMap = new ConcurrentHashMap(16);
private final AtomicBoolean running = new AtomicBoolean(false);
private final AtomicLong nacosWatchIndex = new AtomicLong(0L);
private ApplicationEventPublisher publisher;
private ScheduledFuture<?> watchFuture;
private NacosServiceManager nacosServiceManager;
private final NacosDiscoveryProperties properties;
private final ThreadPoolTaskScheduler taskScheduler;
public NacosWatch(NacosServiceManager nacosServiceManager, NacosDiscoveryProperties properties) {
this.nacosServiceManager = nacosServiceManager;
this.properties = properties;
this.taskScheduler = getTaskScheduler();
}
private static ThreadPoolTaskScheduler getTaskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setBeanName("Nacos-Watch-Task-Scheduler");
taskScheduler.initialize();
return taskScheduler;
}
public void initialize() {
if (this.logger.isInfoEnabled()) {
this.logger.info("Initializing ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (!this.threadNamePrefixSet && this.beanName != null) {
this.setThreadNamePrefix(this.beanName + "-");
}
#使用AbortPolicy策略:丢弃任务并抛出RejectedExecutionException异常
this.executor = this.initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
}
}
NacosDiscoveryAutoConfiguration
@Configuration
@EnableConfigurationProperties
@ConditionalOnNacosDiscoveryEnabled
@ConditionalOnProperty(
value = {"spring.cloud.service-registry.auto-registration.enabled"},
matchIfMissing = true
)
@AutoConfigureAfter({AutoServiceRegistrationConfiguration.class, AutoServiceRegistrationAutoConfiguration.class})
public class NacosDiscoveryAutoConfiguration {
public NacosDiscoveryAutoConfiguration() {
}
@Bean
public NacosServiceRegistry nacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
return new NacosServiceRegistry(nacosDiscoveryProperties);
}
@Bean
@ConditionalOnBean({AutoServiceRegistrationProperties.class})
public NacosRegistration nacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties, ApplicationContext context) {
return new NacosRegistration(nacosDiscoveryProperties, context);
}
@Bean
@ConditionalOnBean({AutoServiceRegistrationProperties.class})
public NacosAutoServiceRegistration nacosAutoServiceRegistration(NacosServiceRegistry registry, AutoServiceRegistrationProperties autoServiceRegistrationProperties, NacosRegistration registration) {
return new NacosAutoServiceRegistration(registry, autoServiceRegistrationProperties, registration);
}
}
NacosRegistration
public class NacosRegistration implements Registration, ServiceInstance {
public static final String MANAGEMENT_PORT = "management.port";
public static final String MANAGEMENT_CONTEXT_PATH = "management.context-path";
public static final String MANAGEMENT_ADDRESS = "management.address";
public static final String MANAGEMENT_ENDPOINT_BASE_PATH = "management.endpoints.web.base-path";
private NacosDiscoveryProperties nacosDiscoveryProperties;
private ApplicationContext context;
public NacosRegistration(NacosDiscoveryProperties nacosDiscoveryProperties, ApplicationContext context) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
this.context = context;
}
@PostConstruct
public void init() {
Map<String, String> metadata = this.nacosDiscoveryProperties.getMetadata();
Environment env = this.context.getEnvironment();
String endpointBasePath = env.getProperty("management.endpoints.web.base-path");
if (!StringUtils.isEmpty(endpointBasePath)) {
metadata.put("management.endpoints.web.base-path", endpointBasePath);
}
Integer managementPort = ManagementServerPortUtils.getPort(this.context);
if (null != managementPort) {
metadata.put("management.port", managementPort.toString());
String contextPath = env.getProperty("management.server.servlet.context-path");
String address = env.getProperty("management.server.address");
if (!StringUtils.isEmpty(contextPath)) {
metadata.put("management.context-path", contextPath);
}
if (!StringUtils.isEmpty(address)) {
metadata.put("management.address", address);
}
}
if (null != this.nacosDiscoveryProperties.getHeartBeatInterval()) {
metadata.put("preserved.heart.beat.interval", this.nacosDiscoveryProperties.getHeartBeatInterval().toString());
}
if (null != this.nacosDiscoveryProperties.getHeartBeatTimeout()) {
metadata.put("preserved.heart.beat.timeout", this.nacosDiscoveryProperties.getHeartBeatTimeout().toString());
}
if (null != this.nacosDiscoveryProperties.getIpDeleteTimeout()) {
metadata.put("preserved.ip.delete.timeout", this.nacosDiscoveryProperties.getIpDeleteTimeout().toString());
}
}
}
NacosServiceRegistry
public class NacosServiceRegistry implements ServiceRegistry<Registration> {
private static final Logger log = LoggerFactory.getLogger(NacosServiceRegistry.class);
private final NacosDiscoveryProperties nacosDiscoveryProperties;
private final NamingService namingService;
public NacosServiceRegistry(NacosDiscoveryProperties nacosDiscoveryProperties) {
this.nacosDiscoveryProperties = nacosDiscoveryProperties;
#这里会将namingService 注册进容器
this.namingService = nacosDiscoveryProperties.namingServiceInstance();
}
public NamingService namingServiceInstance() {
if (null != this.namingService) {
return this.namingService;
} else {
try {
#这里通过构造器反射获取实例
this.namingService = NacosFactory.createNamingService(this.getNacosProperties());
} catch (Exception var2) {
log.error("create naming service error!properties={},e=,", this, var2);
return null;
}
return this.namingService;
}
}
}
NacosNamingService
public class NacosNamingService implements NamingService {
private static final String DEFAULT_PORT = "8080";
private static final long DEFAULT_HEART_BEAT_INTERVAL;
private String namespace;
private String endpoint;
private String serverList;
private String cacheDir;
private String logName;
private HostReactor hostReactor;
private BeatReactor beatReactor;
private EventDispatcher eventDispatcher;
private NamingProxy serverProxy;
public NacosNamingService(String serverList) {
Properties properties = new Properties();
properties.setProperty("serverAddr", serverList);
this.init(properties);
}
public NacosNamingService(Properties properties) {
this.init(properties);
}
private void init(Properties properties) {
this.namespace = InitUtils.initNamespaceForNaming(properties);
this.initServerAddr(properties);
InitUtils.initWebRootContext();
this.initCacheDir();
this.initLogName(properties);
this.eventDispatcher = new EventDispatcher();
this.serverProxy = new NamingProxy(this.namespace, this.endpoint, this.serverList);
this.serverProxy.setProperties(properties);
this.beatReactor = new BeatReactor(this.serverProxy, this.initClientBeatThreadCount(properties));
this.hostReactor = new HostReactor(this.eventDispatcher, this.serverProxy, this.cacheDir, this.isLoadCacheAtStart(properties), this.initPollingThreadCount(properties));
}
private int initClientBeatThreadCount(Properties properties) {
return properties == null ? UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT : NumberUtils.toInt(properties.getProperty("namingClientBeatThreadCount"), UtilAndComs.DEFAULT_CLIENT_BEAT_THREAD_COUNT);
}
}
NacosDiscoveryProperties
@ConfigurationProperties("spring.cloud.nacos.discovery")
public class NacosDiscoveryProperties {
private static final Logger log = LoggerFactory.getLogger(NacosDiscoveryProperties.class);
private String serverAddr;
private String endpoint; # 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
private String namespace;
private long watchDelay = 30000L;
private String logName;# 日志文件名
@Value("${spring.cloud.nacos.discovery.service:${spring.application.name:}}")
private String service;
private float weight = 1.0F;#取值范围 1 到 100,数值越大,权重越大
private String clusterName = "DEFAULT";
private String namingLoadCacheAtStart = "false";
private Map<String, String> metadata = new HashMap();#使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
private boolean registerEnabled = true;
private String ip;# 优先级最高
private String networkInterface = "";#当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址
private int port = -1;# 默认情况下不用配置,会自动探测
private boolean secure = false;
private String accessKey;# 当要上阿里云时,阿里云上面的一个云账号名
private String secretKey;# 当要上阿里云时,阿里云上面的一个云账号密码
private Integer heartBeatInterval;
private Integer heartBeatTimeout;
private Integer ipDeleteTimeout;
@Autowired
private InetUtils inetUtils;
@Autowired
private Environment environment;
private NamingService namingService;
private NamingMaintainService namingMaintainService;
public NacosDiscoveryProperties() {
}
@PostConstruct
public void init() throws SocketException {
this.metadata.put("preserved.register.source", "SPRING_CLOUD");
if (this.secure) {
this.metadata.put("secure", "true");
}
this.serverAddr = Objects.toString(this.serverAddr, "");
if (this.serverAddr.lastIndexOf("/") != -1) {
this.serverAddr = this.serverAddr.substring(0, this.serverAddr.length() - 1);
}
this.endpoint = Objects.toString(this.endpoint, "");
this.namespace = Objects.toString(this.namespace, "");
this.logName = Objects.toString(this.logName, "");
if (StringUtils.isEmpty(this.ip)) {
if (StringUtils.isEmpty(this.networkInterface)) {
this.ip = this.inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
} else {
NetworkInterface netInterface = NetworkInterface.getByName(this.networkInterface);
if (null == netInterface) {
throw new IllegalArgumentException("no such interface " + this.networkInterface);
}
Enumeration inetAddress = netInterface.getInetAddresses();
while(inetAddress.hasMoreElements()) {
InetAddress currentAddress = (InetAddress)inetAddress.nextElement();
if (currentAddress instanceof Inet4Address && !currentAddress.isLoopbackAddress()) {
this.ip = currentAddress.getHostAddress();
break;
}
}
if (StringUtils.isEmpty(this.ip)) {
throw new RuntimeException("cannot find available ip from network interface " + this.networkInterface);
}
}
}
this.overrideFromEnv(this.environment);
}
}