NacosFactory (获取工厂的统一入口)
// 通过配置类获取 ConfigService
public static ConfigService createConfigService(Properties properties) throws NacosException {
return ConfigFactory.createConfigService(properties);
}
// 通过服务端地址获取 ConfigService
public static ConfigService createConfigService(String serverAddr) throws NacosException {
return ConfigFactory.createConfigService(serverAddr);
}
com.alibaba.nacos.api.NacosFactory 工厂类
提供获取ConfigFactory、NamingFactory、NamingMaintainFactory工厂的静态方法。
设计模式:典型的 工厂模式 应用
ConfigService (分布式配置接口)
// 根据dataid、group获取配置信息
String getConfig(String dataId, String group, long timeoutMs) throws NacosException;
String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) throws NacosException;
// 针对dataid、group增加监听器
void addListener(String dataId, String group, Listener listener) throws NacosException;
// 发布配置
boolean publishConfig(String dataId, String group, String content) throws NacosException;
// 删除配置
boolean removeConfig(String dataId, String group) throws NacosException;
// 删除监听器
void removeListener(String dataId, String group, Listener listener);
// 服务状态
String getServerStatus();
// 关闭回收状态
void shutDown() throws NacosException;
com.alibaba.nacos.api.config.ConfigService
提供了一些针对配置的CRUD操作以及监听配置的变更的能力
NacosConfigService (分布式配置接口实现)
// http 代理类 根据名字就可以知道这个主要用于http协议对外交互
private final HttpAgent agent;
// long polling
private final ClientWorker worker;
private String namespace;
// 关于配置的过滤器管理类
private final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager();
HttpAgent (http 代理类)
void start() throws NacosException;
HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception;
HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception;
HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception;
MetricsHttpAgent
public class MetricsHttpAgent implements HttpAgent {
// 持有真正发起请求的 httpAgent
private final HttpAgent httpAgent;
public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues, String encode, long readTimeoutMs) throws Exception {
Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA");
HttpRestResult<String> result;
try {
result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);
} catch (IOException e) {
throw e;
} finally {}
return result;
}
}
ServerHttpAgent
public class ServerHttpAgent implements HttpAgent {
// 核心类:nacosRestTemplate
// 和springboot RestTemplate差不多 使用http协议对外交互
private static final NacosRestTemplate NACOS_RESTTEMPLATE = ConfigHttpClientManager.getInstance() .getNacosRestTemplate();
// 针对 nacosRestTemplate 进行安全配置
private SecurityProxy securityProxy;
// 调度器
private ScheduledExecutorService executorService;
}
ServerListManager
public class ServerListManager implements Closeable {
volatile List<String> serverUrls = new ArrayList<String>();
}
维护多个服务端地址
SecurityProxy
public class SecurityProxy {
private String accessToken;
private long tokenTtl;
private long lastRefreshTime;
public boolean login(List<String> servers) {
if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS .toMillis(tokenTtl - tokenRefreshWindow)) {
return true;
}
for (String server : servers) {
if (login(server)) {
lastRefreshTime = System.currentTimeMillis();
return true;
}
}
return false;
}
}
SecurityProxy 会调用服务端进行登录,获取到的accessToken和有效时间进行储存。如果失效了会重新发起登录。
NacosRestTemplate
public class NacosRestTemplate extends AbstractNacosRestTemplate {
// 具体的http client
// httpclient有两种实现 1:使用Apache HttpClient 2:使用JDK HttpUrlConnection
private final HttpClientRequest requestClient;
// http调用 拦截器 可以根据需求 定制自己的拦截器
private final List<HttpClientRequestInterceptor> interceptors = new ArrayList<HttpClientRequestInterceptor>();
}
HttpClientRequest
public interface HttpClientRequest extends Closeable {
// 执行请求并且返回结果
HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) throws Exception;
}
http调用统一接口
DefaultHttpClientRequest
public class DefaultHttpClientRequest implements HttpClientRequest {
// implementation that uses apache http client to execute streaming requests.
// 使用 appche http client 实现
private final CloseableHttpClient client;
}
HttpClientRequest 默认实现
JdkHttpClientRequest
public class JdkHttpClientRequest implements HttpClientRequest {
private HttpClientConfig httpClientConfig;
public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity){
………………
HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();
………………
}
}
使用java net包实现
InterceptingHttpClientRequest
public class InterceptingHttpClientRequest implements HttpClientRequest {
// 持有httpClientRequest 进行包装
private final HttpClientRequest httpClientRequest;private final Iterator<HttpClientRequestInterceptor> interceptors;
public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity){
while (interceptors.hasNext()) {
HttpClientRequestInterceptor nextInterceptor = interceptors.next();
if (nextInterceptor.isIntercept(uri, httpMethod, requestHttpEntity)) {
return nextInterceptor.intercept();
}
return httpClientRequest.execute(uri, httpMethod, requestHttpEntity);
}
}
包装了httpClientRequest,在执行httpClientRequest.execute 增加了拦截逻辑。
ClientWorker
public class ClientWorker implements Closeable {
…………
// 缓存了 配置信息 key = dataId+GroupId
private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>( new HashMap<String, CacheData>());
…………
}
checkConfigInfo 会根据cacheMap.size 进行维护
ConfigService.getConfig 伪代码
// 校验参数 + 默认配置
// 优先使用本地配置
String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
if(content != null) return content;
// 从服务端获取配置信息 && 如果成功保存快照版本
try{
String[] ct = worker.getServerConfig(dataId, group, tenant, timeoutMs);
} …………
// 如果从服务端获取异常 直接获取本地快照版本返回
content = LocalConfigInfoProcessor.getSnapshot(agent.getName(), dataId, group, tenant);
return content;
涉及到的模式:
1、工厂模式 NacosFactory 典型的简单工厂
2、模板模式 NacosRestTemplate
3、装饰器模式 MetricsHttpAgent
以上就是针对ConfigService客户端的分析 ,下一章进行服务端分析。