logo头像

Edward.K Thinking

使用Azure Function驅動Azure Analysis Services的Model同步

Azure Analysis Services是一個在雲端的Analysis Services服務,其作用跟地端的Analysis Services功能是類似的,第一步都必須把資料從DataWare house或是Database等資料儲存體匯入到Analysis Services中(當然也可以讓AS做直接Query DB),然後再用其他工具與Analysis Services進行資料視覺化的呈現。因此,第一步匯入資料就很重要,再加上Analysis Services本身開啟就是會有費用,如果可以知道用戶習慣,非必要時期也可以關閉Analysis Services服務。所以,在這些情境下,就必須要做資料同步,不然資料會不存在Module。

為了做到不只可以同步Module外,也可以做到能自動化,因此,透過Azure Function的Timer來進行。

註冊一個Azure應用程式


首先就是必須建立一個Azure Function 服務,同時在AAD上面需要註冊該Azure Function服務,這樣才可以透過AF去操作AS。


選下新增應用程式註冊,填好下列資訊,其中重新導向URI這一個可以先暫時用localhost,後續是可以被修改的。不過,基本上在這邊也不太會用到


註冊好之後,其中必須把應用程式識別碼資訊給記下來,後續程式會用到這ID做身分的識別

建立Azure Function


因為想要做到定時去同步AS的功能,所以這邊就必須使用Timer類型的Azure Function。在開發這功能的第一個步驟,就是必須讓AF透過AAD取得Token後,再跟Azure Analysis Services API進行溝通,服務與服務之間建議透過API進行交握,一方面不僅比較簡單外,處理起來也會相對彈性和擴充較佳。跟AAD取得Toke語法,要跟AAD取得Token方法很多種,其中一種就是透過上面的應用程式識別碼和建立一組AD作為服務間帳號。當然這AAD帳號同時必須能被授權操作Azure Analysis Services才可以

1
2
3
4
5
6
7
8
9
10
public async Task<string> GetToken()
{
string resourceURI = "https://*.asazure.windows.net";
string authority = "https://login.windows.net/common/oauth2/authorize";
AuthenticationContext ac = new AuthenticationContext(authority);

UserPasswordCredential cred = new UserPasswordCredential("AAD帳號, "AAD帳號的密碼");
AuthenticationResult ar = await ac.AcquireTokenAsync(resourceURI, 應用程式識別碼, cred);
return ar.AccessToken;
}

在Azure Analysis Services的API流程如下圖。


要傳送的Json格式會如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"Type": "Full",
"CommitMode": "transactional",
"MaxParallelism": 2,
"RetryCount": 2,
"Objects": [
{
"table": "DimCustomer",
"partition": "DimCustomer"
},
{
"table": "DimDate"
}
]
}


基於這些資訊,我們可以建立其相關功能,這部分我們需要知道Analysis Service在那個資訊中心、Analysis Service的Server Name以及要更新的Module Name。並利用RefreshRequestModel建立要更新資訊的設定給Analysis Service,RefreshRequestMode其他屬性可以參考文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public async void RefreshAsync(TraceWriter log, string AnalysisServiceslocaltion, string ServerName, string ModelName)
{
HttpClient client = new HttpClient();

try
{
client.BaseAddress = new Uri($"https://{AnalysisServiceslocaltion}.asazure.windows.net/servers/{ServerName}/models/{ModelName}/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await new GetToken());

RefreshRequestModel refreshRequest = new RefreshRequestModel()
{
type = "full",
maxParallelism = 10
};

HttpResponseMessage response = await client.PostAsJsonAsync("refreshes", refreshRequest);
if (!response.IsSuccessStatusCode)
{
log.Warning("Async faile");
}
Uri location = response.Headers.Location;
log.Info(response.Headers.Location.ToString());
}
catch (Exception e)
{
log.Error(e.Message);
}
}


以上功能建立好,這時候在Azure Function只要設定好時間去呼叫這個sync就可以

1
2
3
4
public static void RunSyncReflow([TimerTrigger("0 15 8 * * 1-5")]TimerInfo myTimer, TraceWriter log)
{
new RefreshAsync(log, "southeastasia", "ASServerName", "ModuleName");
}


時間到就會自動去同步AS的Module了

參考資源