Diamond部署之坑

这里先说/diamond-utils/src/main/java/com/taobao/diamond/common/Constants.java这个文件必须改动的三个字段

public static final String HTTP_URI_FILE = "/diamond-server/config.co";//这个是为了从服务端提取配置信息

public static final String CONFIG_HTTP_URI_FILE = "/url";//这个是为了获取服务端地址列表的请求地址,后面会说到

public static final int DEFAULT_PORT = 0;//这里面为服务端的端口,默认为0,需要被改成真正的提供服务端口

获取配置信息测试的代码:

 1 package com.taobao.diamond.test;
 2 import java.util.concurrent.Executor;
 3 import com.taobao.diamond.manager.DiamondManager;
 4 import com.taobao.diamond.manager.ManagerListener;
 5 import com.taobao.diamond.manager.impl.DefaultDiamondManager;
 6 public class DiamondClient {
 7     public static void main(String[] str) {
 8         DiamondManager manager = new DefaultDiamondManager("DEFAULT_GROUP", "topicConfig",
 9             new ManagerListener() {//填写你服务端后台保存过的group和dataId
10             public void receiveConfigInfo(String configInfo) {
11                 System.out.println("changed config: " + configInfo);
12             }
13             public Executor getExecutor() {
14             return null;
15             }
16         }, "127.0.0.1,10.126.53.16,10.126.53.17");
17         //设置diamond-server服务的端口
18         manager.getDiamondConfigure().setPort(8080);
19 
20         String availableConfigureInfomation = manager.getAvailableConfigureInfomation(5000);
21         System.out.println("start config: " + availableConfigureInfomation);
22     }
23 }

 

对DefaultDiamondManager的扩展,支持手动指定服务端地址

添加了它的一个构造函数

 1  public DefaultDiamondManager(String group, String dataId, ManagerListener managerListener,String diamondServer) {
 2         this.dataId = dataId;
 3         this.group = group;
 4 
 5         diamondSubscriber = DiamondClientFactory.getSingletonDiamondSubscriber();
 6 
 7         this.managerListeners.add(managerListener);
 8         ((DefaultSubscriberListener) diamondSubscriber.getSubscriberListener()).addManagerListeners(this.dataId,
 9             this.group, this.managerListeners);
10         String s[] = diamondServer.split(",");
11         if (s != null && s.length > 0) {
12             for (String o : s) {
13             if (o != null && !o.trim().equals(""))
14                 diamondSubscriber.getDiamondConfigure().getDomainNameList().add(o.trim());
15             }
16         }
17         diamondSubscriber.addDataId(this.dataId, this.group);
18         diamondSubscriber.start();
19     }

 

这样的话,就能获取到配置信息了。

上面这个例子通过手动指定diamondServer可以跳过服务端寻址的这个过程。

在配置diamond-server集群的时候,各个server之间的端口并没有要求相同,

但是在这的时候,发现它的端口,只能是相同的,无法每个IP对应自己的端口。

所以这里的diamondServer地址应该是nginx地址,端口的话,也应该是nginx提供diamond-server服务的端口。

nginx提供负载均衡的策略,同一的访问域名,对应了多台diamond-server后台机器,这里面的端口可以是不同的,解决diamond-server的单点问题。

虽然上面的那个例子手动指定了diamondServer地址,但是我们还是要去大体了解获取服务端地址的逻辑。

new DefaultDiamondManager的构造函数,最后一句是diamondSubscriber.start();

点击进去

  1 serverAddressProcessor = new ServerAddressProcessor(this.diamondConfigure, this.scheduledExecutor);
  2 
  3 serverAddressProcessor.start();
  4 
  5 然后在查看serverAddressProcessor.start()的具体逻辑
  6 
  7     public synchronized void start() {
  8         if (isRun) {
  9             return;
 10         }
 11         isRun = true;
 12         initHttpClient();
 13         if (this.diamondConfigure.isLocalFirst()) {
 14             acquireServerAddressFromLocal();
 15         }
 16         else {
 17             synAcquireServerAddress();//首先执行的是这个
 18             asynAcquireServerAddress();
 19         }
 20     }
 21     protected void synAcquireServerAddress() {
 22         if (!isRun) {
 23             throw new RuntimeException("ServerAddressProcessor不在运行状态,无法同步获取服务器地址列表");
 24         }
 25         if (MockServer.isTestMode()) {
 26             diamondConfigure.addDomainName("测试模式,没有使用的真实服务器");
 27             return;
 28         }
 29         int acquireCount = 0;
 30         if (diamondConfigure.getDomainNameList().size() == 0) {
 31             if (!acquireServerAddressOnce(acquireCount)) {
 32                 acquireCount++;
 33                 if (acquireServerAddressOnce(acquireCount)) {
 34                     // 存入本地文件
 35                     storeServerAddressesToLocal();
 36                     log.info("在同步获取服务器列表时,向日常ConfigServer服务器获取到了服务器列表");
 37                 }
 38                 else {
 39                     log.info("从本地获取Diamond地址列表");
 40                     reloadServerAddresses();
 41                     if (diamondConfigure.getDomainNameList().size() == 0)
 42                         throw new RuntimeException("当前没有可用的服务器列表");
 43                 }
 44             }
 45             else {
 46                 log.info("在同步获取服务器列表时,向线上ConfigServer服务器获取到了服务器列表");
 47                 // 存入本地文件
 48                 storeServerAddressesToLocal();
 49             }
 50         }
 51     }
 52 
 53     private boolean acquireServerAddressOnce(int acquireCount) {
 54         HostConfiguration hostConfiguration = configHttpClient.getHostConfiguration();
 55         String configServerAddress;
 56         int port;
 57         if (null != diamondConfigure.getConfigServerAddress()) {
 58             configServerAddress = diamondConfigure.getConfigServerAddress();
 59             port = diamondConfigure.getConfigServerPort();
 60         }
 61         else {
 62             if (acquireCount == 0) {
 63                 configServerAddress = Constants.DEFAULT_DOMAINNAME;//a.b.c
 64                 port = Constants.DEFAULT_PORT;//端口
 65             }
 66             else {
 67                 configServerAddress = Constants.DAILY_DOMAINNAME;//d.e.f
 68                 port = Constants.DEFAULT_PORT;//端口
 69             }
 70         }
 71         hostConfiguration.setHost(configServerAddress, port);
 72 
 73         String serverAddressUrl = Constants.CONFIG_HTTP_URI_FILE;
 74         //默认为/url,并且配置域名a.b.c或者d.e.f 访问url==>http://a.b.c:port/url返回以换行分隔的diamond ip列表行.
 75         //所以这个/url很有可能需要被改掉
 76         HttpMethod httpMethod = new GetMethod(serverAddressUrl);
 77         // 设置HttpMethod的参数
 78         HttpMethodParams params = new HttpMethodParams();
 79         params.setSoTimeout(diamondConfigure.getOnceTimeout());
 80         // ///////////////////////
 81         httpMethod.setParams(params);
 82 
 83         try {
 84             if (SC_OK == configHttpClient.executeMethod(httpMethod)) {
 85                 InputStreamReader reader = new InputStreamReader(httpMethod.getResponseBodyAsStream());
 86                 BufferedReader bufferedReader = new BufferedReader(reader);
 87                 String address = null;
 88                 List<String> newDomainNameList = new LinkedList<String>();
 89                 while ((address = bufferedReader.readLine()) != null) {//以换行分割
 90                     address = address.trim();
 91                     if (StringUtils.isNotBlank(address)) {
 92                         newDomainNameList.add(address);
 93                     }
 94                 }
 95                 if (newDomainNameList.size() > 0) {
 96                     log.debug("更新使用的服务器列表");
 97                     this.diamondConfigure.setDomainNameList(newDomainNameList);
 98                     return true;
 99                 }
100             }
101             else {
102                 log.warn("没有可用的新服务器列表");
103             }
104         }
105         catch (HttpException e) {
106             log.error(getErrorMessage(configServerAddress) + ", " + e);
107         }
108         catch (IOException e) {
109             log.error(getErrorMessage(configServerAddress) + ", " + e);
110         }
111         catch (Exception e) {
112             log.error(getErrorMessage(configServerAddress) + ", " + e);
113         }
114         finally {
115             httpMethod.releaseConnection();
116         }
117         return false;
118     }

 

函数reloadServerAddresses,本地获取服务地址列表

File serverAddressFile = new File(generateLocalFilePath(this.diamondConfigure.getFilePath(), "ServerAddress"));

//这里的地址,在我的机器,默认为C:\Users\linchengjun\diamond\ServerAddress

============================分割线==========================================

到这为止,diamond-client获取server列表的顺序出来了

1.如果像我那样对DefaultDiamondManager进行了扩展,手动指定了地址列表,就不会进行其他的寻址逻辑了。

2.如果没有的话,先进行http://a.b.c:port/url请求sever地址列表行,获取不到,再进行http://d.e.f:port/url请求获取;

如果这两个都不行,就会调用reloadServerAddresses,进行本地文件的获取,比如C:\Users\linchengjun\diamond\ServerAddress

--------------------------------------------------读取服务端配置信息的顺序------------------------------------

分析测试代码

 1  String availableConfigureInfomation = manager.getAvailableConfigureInfomation(5000);
 2     public String getAvailableConfigureInfomation(String dataId, String group, long timeout) {
 3         // 尝试先从本地和网络获取配置信息
 4         try {
 5             String result = getConfigureInfomation(dataId, group, timeout);
 6             if (result != null && result.length() > 0) {
 7                 return result;
 8             }
 9         }
10         catch (Throwable t) {
11             log.error(t.getMessage(), t);
12         }
13 
14         // 测试模式不使用本地dump
15         if (MockServer.isTestMode()) {
16             return null;
17         }
18         return getSnapshotConfiginfomation(dataId, group);//从快照文件获取
19     }

 

具体断点进行调试,就能总结出来,读取的顺序

  1. 先从本地缓存读取
  2. 发现本地缓存localConfigInfoProcessor并没有缓存住,就从网络提取,这个时候需要注意Constants.HTTP_URI_FILE这个值,需要被改成/diamond-server/config.co

    要不然老是获取不正确,即Constants.java中HTTP_URI_FILE改成public static final String HTTP_URI_FILE = "/diamond-server/config.co";

    从网络获取到数据之后,会先保存到快照里面,然后是保存到本地缓存。

  3. 从本地快照文件获取

你可能感兴趣的:(Diamond部署之坑)