[從原始碼學設計]螞蟻金服SOFARegistry之配置資訊
阿新 • • 發佈:2021-01-20
# [從原始碼學設計]螞蟻金服SOFARegistry之配置資訊
[toc]
## 0x00 摘要
SOFARegistry 是螞蟻金服開源的一個生產級、高時效、高可用的服務註冊中心。
本系列文章重點在於分析設計和架構,即利用多篇文章,從多個角度反推總結 DataServer 或者 SOFARegistry 的實現機制和架構思路,讓大家藉以學習阿里如何設計。
本文為第十七篇,介紹SOFARegistry網路操作之配置資訊如何處理。
## 0x01 業務範疇
### 1.1 配置作用
比如某些系統相關的服務,需要由控制檯來設定。所以Meta Server對控制檯提供了介面,當Meta Server 接受到控制檯請求後,會和 Data Server,Session Server 進行互動,比如Meta Server 提供瞭如下介面:
```java
@Bean
@ConditionalOnMissingBean
public StopPushDataResource stopPushDataResource() {
return new StopPushDataResource();
}
@Bean
public BlacklistDataResource blacklistDataResource() {
return new BlacklistDataResource();
}
@Bean
public RenewSwitchResource renewSwitchResource() {
return new RenewSwitchResource();
}
```
對外提供http介面,是因為這是正常基本操作。但是Server之間依然是Bolt協議操作。
### 1.2 學習方向
此處推導如下:在DataServer端,如何把配置資訊單獨摘出來。
## 0x02 資料結構
### 2.1 目錄結構
DataServer之中,配置相關目錄如下,可以看到有Handler,服務,task以及provideData。
```java
│ ├── metaserver
│ │ ├── DefaultMetaServiceImpl.java
│ │ ├── IMetaServerService.java
│ │ ├── MetaServerConnectionFactory.java
│ │ ├── handler
│ │ │ ├── NotifyProvideDataChangeHandler.java
│ │ │ ├── ServerChangeHandler.java
│ │ │ └── StatusConfirmHandler.java
│ │ ├── provideData
│ │ │ ├── ProvideDataProcessor.java
│ │ │ ├── ProvideDataProcessorManager.java
│ │ │ └── processor
│ │ │ └── DatumExpireProvideDataProcessor.java
│ │ └── task
```
### 2.2 資料結構定義
配置相關資料結構如下:
ProvideData是對外的互動介面,裡面是版本號和服務標示dataInfoId。
```java
public class ProvideData implements Serializable {
private ServerDataBox provideData;
private String dataInfoId;
private Long version;
}
```
ServerDataBox是具體業務,其定義如下
```java
public class ServerDataBox implements Serializable {
/** Null for locally instantiated, otherwise for internalized */
private byte[] bytes;
/** Only available if bytes != null */
private int serialization;
/** Actual object, lazy deserialized */
private Object object;
}
```
關於ServerDataBox,目前在Data Server只有一處使用。使用的是boolean型別,也就是控制開關配置。
```java
public void changeDataProcess(ProvideData provideData) {
boolean enableDataDatumExpire = Boolean.parseBoolean((String) provideData.getProvideData()
.getObject());
datumLeaseManager.setRenewEnable(enableDataDatumExpire);
}
```
## 0x03 Meta Server 內流程
這裡為了打通流程,需要先提一下 meta server 內部與 metaServerService.fetchData(dataInfoId) 相關的流程。
處於解耦的目的,Meta Server 把某些業務功能分割成四個層次,基本邏輯是:
```java
Http Resource ———> TaskListener ———> Task ————> Service
```
首先給出流程圖如下,下文會逐步介紹流程:
```java
+------------------------+
| | 2 +-------------------------+
| BlacklistDataResource +------>-+PersistenceDataDBService |
| | update +-------------------------+ 7
+-------+ 1 | | +---------------------------------------+
| Admin | +---> | +--------------------- | | Data Server |
+-------+ | |fireDataChangeNotify| | | |
| +--------------------+ | 6 | +-----------------------------------+ |
+------------------------+ | | metaClientHandlers | |
| +---------------------+ dataNodeExchanger.request | | +-------------------------------+ | |
| 3 | DataNodeServiceImpl | +----------------------------->+ | | notifyProvideDataChangeHandler| | |
| +----------+----------+ NotifyProvideDataChange | | +-------------------------------+ | |
| NotifyProvideDataChange ^ | | | |
| | | +-----------------------------------+ |
| 5 | notifyProvideDataChange +---------------------------------------+
v |
+---------+-----------------------------------+ |
| DefaultTaskListenerManager | |
| | +----+----------------------------+
| +-----------------------------------------+ | 4 | |
| | persistenceDataChangeNotifyTaskListener | +------>+ PersistenceDataChangeNotifyTask |
| | | | | |
| | receiveStatusConfirmNotifyTaskListener | | +---------------------------------+
| | | |
| | dataNodeChangePushTaskListener | |
| | | |
| | sessionNodeChangePushTaskListener | |
| +-----------------------------------------+ |
+---------------------------------------------+
```
手機圖示如下 :
![](https://img2020.cnblogs.com/blog/1850883/202101/1850883-20210117155437563-806879240.png)
### 3.1 Admin請求響應
前面提到,Meta Server 通過 Http協議給Admin提供了一些控制介面,下面我們就以 BlacklistDataResource 為例研究下。
可以看到,blacklistPush 函式中會先儲存在 persistenceDataDBService 中,然後 fireDataChangeNotify 間接傳送 NotifyProvideDataChange。
```java
@Path("blacklist")
public class BlacklistDataResource {
@RaftReference
private DBService persistenceDataDBService;
@Autowired
private TaskListenerManager taskListenerManager;
/**
* update blacklist
* e.g. curl -d '{"FORBIDDEN_PUB":{"IP_FULL":["1.1.1.1","10.15.233.150"]},"FORBIDDEN_SUB_BY_PREFIX":{"IP_FULL":["1.1.1.1"]}}' -H "Content-Type: application/json" -X POST http://localhost:9615/blacklist/update
*/
@POST
@Path("update")
@Produces(MediaType.APPLICATION_JSON)
public Result blacklistPush(String config) {
PersistenceData persistenceData = createDataInfo();
persistenceData.setData(config);
boolean ret = persistenceDataDBService.update(ValueConstants.BLACK_LIST_DATA_ID,
persistenceData);
fireDataChangeNotify(persistenceData.getVersion(), ValueConstants.BLACK_LIST_DATA_ID,
DataOperator.UPDATE);
Result result = new Result();
result.setSuccess(true);
return result;
}
private PersistenceData createDataInfo() {
DataInfo dataInfo = DataInfo.valueOf(ValueConstants.BLACK_LIST_DATA_ID);
PersistenceData persistenceData = new PersistenceData();
persistenceData.setDataId(dataInfo.getDataId());
persistenceData.setGroup(dataInfo.getDataType());
persistenceData.setInstanceId(dataInfo.getInstanceId());
persistenceData.setVersion(System.currentTimeMillis());
return persistenceData;
}
private void fireDataChangeNotify(Long version, String dataInfoId, DataOperator dataOperator) {
NotifyProvideDataChange notifyProvideDataChange = new NotifyProvideDataChange(dataInfoId,
version, dataOperator);
TaskEvent taskEvent = new TaskEvent(notifyProvideDataChange,
TaskType.PERSISTENCE_DATA_CHANGE_NOTIFY_TASK);
taskListenerManager.sendTaskEvent(taskEvent);
}
}
```
這裡對應上圖的:
```java
+------------------------+
| | 2 +-------------------------+
| BlacklistDataResource +------>-+PersistenceDataDBService |
| | update +-------------------------+
+-------+ 1 | |
| Admin | +---> | +--------------------+ |
+-------+ | |fireDataChangeNotify| |
| +--------------------+ |
+------------------------+
```
### 3.2 DBService
可以看到,DBService也是基於 Raft,這說明在MetaServer叢集內部自己維護了一致性。
```java
@RaftReference
private DBService persistenceDataDBService;
```
PersistenceDataDBService 類精簡版定義如下:
```java
@RaftService
public class PersistenceDataDBService extends AbstractSnapshotProcess implements DBService {
private Concurren