1.启动客户端
配置中心客户端代码
import java.util.Properties;
import java.util.concurrent.Executor;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
/**
* Config service example
* sdk
* @author Nacos
*
*/
public class ConfigExample {
public static void main(String[] args) throws NacosException, InterruptedException {
String serverAddr = "localhost";
String dataId = "example";
String group = "DEFAULT_GROUP";
Properties properties = new Properties();
properties.put(PropertyKeyConst.SERVER_ADDR, serverAddr);
ConfigService configService = NacosFactory.createConfigService(properties);
String content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
configService.addListener(dataId, group, new Listener() {
@Override
public void receiveConfigInfo(String configInfo) {
System.out.println("recieve:" + configInfo);
}
@Override
public Executor getExecutor() {
return null;
}
});
boolean isPublishOk = configService.publishConfig(dataId, group, "content");
System.out.println(isPublishOk);
Thread.sleep(3000);
content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
boolean isRemoveOk = configService.removeConfig(dataId, group);
System.out.println(isRemoveOk);
Thread.sleep(3000);
content = configService.getConfig(dataId, group, 5000);
System.out.println(content);
Thread.sleep(300*1000);
}
}
2.启动NacosConfigService
ConfigService configService = NacosFactory.createConfigService(properties)代码中
通过反射实例化NacosConfigService
public class ConfigFactory {
...
public static ConfigService createConfigService(Properties properties) throws NacosException {
try {
Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
Constructor constructor = driverImplClass.getConstructor(Properties.class);
ConfigService vendorImpl = (ConfigService)constructor.newInstance(properties);
return vendorImpl;
} catch (Throwable var4) {
throw new NacosException(-400, var4);
}
}
...
构造方法中初始化参数及启动线程
public class NacosConfigService implements ConfigService {
private static final Logger LOGGER = LogUtils.logger(NacosConfigService.class);
private static final long POST_TIMEOUT = 3000L;
private static final String EMPTY = "";
private HttpAgent agent;
private ClientWorker worker;
private String namespace;
private String encode;
private ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager();
public NacosConfigService(Properties properties) throws NacosException {
String encodeTmp = properties.getProperty("encode");
if (StringUtils.isBlank(encodeTmp)) {
this.encode = "UTF-8";
} else {
this.encode = encodeTmp.trim();
}
this.initNamespace(properties);
this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
this.agent.start();
this.worker = new ClientWorker(this.agent, this.configFilterChainManager, properties);
}
注册中心
MetricsHttpAgent 启动一个单线程的线程池,监听服务器中服务器地址
this.agent = new MetricsHttpAgent(new ServerHttpAgent(properties));
this.agent.start();
会调用到com.alibaba.nacos.client.config.impl.ServerListManager#start
...
public synchronized void start() throws NacosException {
if (!this.isStarted && !this.isFixed) {
ServerListManager.GetServerListTask getServersTask = new ServerListManager.GetServerListTask(this.addressServerUrl);
for(int i = 0; i < this.initServerlistRetryTimes && this.serverUrls.isEmpty(); ++i) {
getServersTask.run();
try {
this.wait((long)(i + 1) * 100L);
} catch (Exception var4) {
LOGGER.warn("get serverlist fail,url: {}", this.addressServerUrl);
}
}
if (this.serverUrls.isEmpty()) {
LOGGER.error("[init-serverlist] fail to get NACOS-server serverlist! env: {}, url: {}", this.name, this.addressServerUrl);
throw new NacosException(500, "fail to get NACOS-server serverlist! env:" + this.name + ", not connnect url:" + this.addressServerUrl);
} else {
TimerService.scheduleWithFixedDelay(getServersTask, 0L, 30L, TimeUnit.SECONDS);
this.isStarted = true;
}
}
}
...
配置中心
this.worker = new ClientWorker(this.agent, this.configFilterChainManager, properties);
启动一个工作线程
ClientWorker 构造器
...
public ClientWorker(final HttpAgent agent, ConfigFilterChainManager configFilterChainManager, Properties properties) {
this.agent = agent;
this.configFilterChainManager = configFilterChainManager;
this.init(properties);
this.executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker." + agent.getName());
t.setDaemon(true);
return t;
}
});
this.executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
t.setDaemon(true);
return t;
}
});
this.executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
ClientWorker.this.checkConfigInfo();
} catch (Throwable var2) {
ClientWorker.LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", var2);
}
}
}, 1L, 10L, TimeUnit.MILLISECONDS);
}
...
检查配置中心配置,如果配置信息超过默认指定大小(数据量过大)则会开启多个线程同时查询配置,每个线程查询指定数量配置(数据分段,多线程查询提高性能)
...
public void checkConfigInfo() {
int listenerSize = ((Map)this.cacheMap.get()).size();
int longingTaskCount = (int)Math.ceil((double)listenerSize / ParamUtil.getPerTaskConfigSize());
if ((double)longingTaskCount > this.currentLongingTaskCount) {
for(int i = (int)this.currentLongingTaskCount; i < longingTaskCount; ++i) {
this.executorService.execute(new ClientWorker.LongPollingRunnable(i));
}
this.currentLongingTaskCount = (double)longingTaskCount;
}
}
...