通過Java調用OceanBase云平臺API

最近由于工作原因又開始搗鼓OceanBase,OceanBase云平臺(OCP)提供了強大的管理和監控功能,而且對外開放API接口,可以將部分監控整合到自己的平臺,所以寫了個Java調用OCP API的demo做為自己的技術儲備,也想分享給大家。也因為最近對Eclipse Vertx和異步編程非常興趣,所以案例使用是Vertx的WebClient,而非Apache HttpClient, 不過,不管用什么庫,原理是相似的。

先介紹下環境,我這邊用的是OCP企業版4.2.2,OB不同版本之間差異還是很大的,其它版本不一定適用。參考的是官方文檔(https://www.oceanbase.com/docs/common-ocp-1000000000585101):云平臺OCP --> “參考指南” --> “API參考”。

客戶端鑒權

OCP開放API的客戶端鑒權,支持使用AK/SK和HTTP Basic兩種認證模式。

HTTP Basic認證模式

HTTP Basic通過用戶名和密碼進行鑒權,相對比較簡單,但因為是明文傳輸,并不安全,特別是使用http時,用戶名和密碼可以在傳輸過程中被抓包解析出來。對于可控的內網,也可以做為便捷的方法。以下是實現代碼(為了文檔更好的閱讀,完整的代碼放在文章的資源中https://download.csdn.net/download/Li_Xiang_996/89517863?spm=1001.2101.3001.9499)。

// 先構建'"用戶名":"用戶密碼"字符串, 然后將字符進行Base64編碼,就可以得到authorization。
byte[] strContents = (userName.trim() + ":" + password.trim()).getBytes();
String base64Contents = Base64.getUrlEncoder().encodeToString(strContents);
String authorization = "Basic " + base64Contents;
// 然后調用API時候,將authorization放到HTTP請求消息頭Authorization中即可。
client.something.putHeader("Authorization", authorization).send();

API(AK/SK)認證模式

OB得官方文檔有詳細介紹如何使用,可以參考。一些題外話,OB的官方文檔相較之前有非常巨大的進步,值得點贊。

首先需要在OCP中創建(申請) AK/SK,登錄OCP,右邊導航點開"系統管理" ->“用戶管理”。用戶列表中選擇一個用戶或者創建一個新用戶,需要注意的是,當獲取了用戶的AccessKey,也就獲得了該用戶的權限。

選擇用戶,進入對應的用戶的設置頁面,在“AccessKey”部分,點擊"一鍵創建 AccessKey",即可獲取該用戶的AK/SK。后續我們就可以通過AK/SK來進行API訪問。

認證原理大致是: 客戶端將(將要)對API的請求按照指定的格式拼接成一個消息(字符串),然后用申請到的AK對應的SK,通過HMACSHA1算法對消息進行加簽(生成消息的哈希串)。

 消息體格式
String message = "POST\n" +    //HTTP請求方法, 大寫英文。包括: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS和TRACE。"186974DB33A090A16D3E2CA35F547B56\n" + // 請求體, md5編碼, 可以為空(如使用HTTP GET時候), 當換行(\n)符號不能省略。"application/json\n" +                 // 消息體的類型。OCP統一使用application/json類型的消息體。"Fri, 5 Jul 2024 06:49:37 GMT\n" +    // 請求發起時間, 其遵循RFC1123格式, 必須是GMT時區?"10.100.6.161:8080\n" +               // OCP服務器地址+端口"x-ocp-date:Fri, 5 Jul 2024 06:49:37 GMT\n" +  //"/api/v2/compute/idcs" //API請求的路徑, 以及請求的查詢參數, 請求參數可以為空, 如果有多個必須按參數名(升序排序), 否則無法通過驗證
 hmacSha1加簽
byte[] hash = hmacSha1(accessKeySecret, message.getBytes(StandardCharsets.UTF_8));
String signature = Base64.getEncoder().encodeToString(hash); 
String authorization = "OCP-ACCESS-KEY-HMACSHA1 " + accessKey + ":" + signature;// 然后調用API時候,將authorization放到HTTP請求消息頭Authorization中即可。
client.something.putHeader("Authorization", authorization).send();

服務器端行為沒看過代碼, 純屬個人猜測, 看個樂吧:服務器端(數據庫中)保存了用戶AK/SK表, 服務器根據接收到請求的Authorization, 可獲取客戶端的AK,就可以查詢到關聯用戶,即可進行權限檢查(是否有權執行); 進一步取出對應的SK,根據服務器獲取的客戶端請求(通過客戶端相同的格式)構建消息體, 并使用SK和相同的HASH算法(HMACSHA1)對消息體進行加簽(計算HASH),如果兩者簽名相同, 那么這通過驗證,返回結果,類似于證書的校驗過程。

調用OCP API

以查詢告警事件列表為例,請求路徑"GET /api/v2/alarm/alarms", 請求參數我們指定每頁顯示5條記錄(size=5), 顯示第一頁(page=1)。

final String baseUri = "/api/v2/alarm/alarms";
Map<String, String> queryParams = new HashMap<>();
queryParams.put("page", "1");
queryParams.put("size", "5");
String uri = AuthorizationBuilder.buildUri(baseUri, queryParams); // buildUri方法會拼接baseUri于查詢參數, 參數按參數名升序組織。 請求時間, 取當前時間, RFC1123格式, 必須為GMT時區
ZonedDateTime requestTime = ZonedDateTime.now(ZoneId.of("GMT"));
String rfc1123RequestTime = DateTimeFormatter.RFC_1123_DATE_TIME.format(requestTime);
根據請求構建authorization, 與上面描述的過程一樣,具體看源代碼。
String authorization = AuthorizationBuilder.newApiAuthorizationBuilder(accessKey, accessKeySecret).setRequestTimestamp(requestTime).setHost(server).setUri(uri).build();
WebClientOptions options = new WebClientOptions().setConnectTimeout(3000);
Vertx vertx = Vertx.vertx();
WebClient client = WebClient.create(vertx, options);
Future<HttpResponse<Buffer>> future = client.get(port, host, uri).putHeader("content-type", AuthorizationBuilder.CONTENT_TYPE_JSON).putHeader("Authorization", authorization).putHeader("x-ocp-date", rfc1123RequestTime).send();
future .onSuccess(AlarmsApi::printResult).onFailure(e -> e.printStackTrace());//解析并打印API返回結果
public static void printResult(HttpResponse<Buffer> response) {JsonObject jsonBody = response.bodyAsJsonObject();boolean successful = jsonBody.getBoolean("successful");if (successful) {JsonObject data = jsonBody.getJsonObject("data");JsonArray contents = data.getJsonArray("contents");System.out.println("###### 告警事件列表(Top 5) ######");for (int i = 0; i < contents.size(); i++) {JsonObject alert = contents.getJsonObject(i);System.out.println("------- " + alert.getLong("id") + " -------" + "\nname: " + alert.getString("name") + "\nalarmType: " + alert.getString("alarmType") + "\nstatus: " + alert.getString("status")+ "\nresolvedAt: " + alert.getString("resolvedAt") + "\ntarget: " + alert.getString("target") + "\ndescription: " + alert.getString("description") + "\n");}} else {System.out.println("API返回失敗! status = " + jsonBody.getInteger("status"));System.out.println(jsonBody.encodePrettily());}
}

執行效果如下:

##### 告警事件列表(Top 5) ######
------- 1000211 -------
name: 服務器CPU平均load1超限
alarmType: ob_host_load1_per_cpu_over_threshold
status: Inactive
resolvedAt: 2024-07-04T21:10:56Z
target: alarm_template_id=0:host=192.168.100.21
description: 集群:metadb,主機:192.168.100.21,告警:服務器CPU平均load1超限。CPU平均load1值 1.552 超過 1.5。------- 1000210 -------
name: 服務器CPU平均load1超限
alarmType: ob_host_load1_per_cpu_over_threshold
status: Inactive
resolvedAt: 2024-07-04T20:56:06Z
target: alarm_template_id=0:host=192.168.100.21
description: 集群:metadb,主機:192.168.100.21,告警:服務器CPU平均load1超限。CPU平均load1值 1.737 超過 1.5。
...

更復雜的調用

OCP API除了查詢還有管理功能(增刪改),以"主機模塊"的機型相關API為例。

  • 查詢機型信息列表: GET /api/v2/compute/hostTypes
  • 添加主機機型信息: POST /api/v2/compute/hostTypes
  • 刪除機型信息: DELETE /api/v2/compute/hostTypes/{hostTypeId}
    Demo代碼:
 新增機型HuaWei_Kunpeng
String postBody = "{\"name\": \"HuaWei_Kunpeng\", \"description\": \"128C 512GB\"}";
String baseUri = "/api/v2/compute/hostTypes";
ZonedDateTime requestTime = ZonedDateTime.now(ZoneId.of("GMT"));
String rfc1123RequestTime = DateTimeFormatter.RFC_1123_DATE_TIME.format(requestTime);String authorization = AuthorizationBuilder.newApiAuthorizationBuilder(accessKey, accessKeySecret).setHttpMethod(HTTP_POST).setRequestTimestamp(requestTime).setHost(server).setUri(uri).setRequestBody(postBody).build();
WebClientOptions options = new WebClientOptions().setConnectTimeout(3000);
WebClient client = WebClient.create(vertx, options);Future<HttpResponse<Buffer>> futrue = client.post(port, host, uri).putHeader("content-type", CONTENT_TYPE_JSON).putHeader("Authorization", authorization).putHeader("x-ocp-date", rfc1123RequestTime).sendBuffer(Buffer.buffer(postBody)); 刪除機型id = 1000010
int hostTypeId = 1000010;
String uri = "/api/v2/compute/hostTypes/" + hostTypeId;
ZonedDateTime requestTime = ZonedDateTime.now(ZoneId.of("GMT"));
String rfc1123RequestTime = DateTimeFormatter.RFC_1123_DATE_TIME.format(requestTime);String authorization = AuthorizationBuilder.newApiAuthorizationBuilder().setHttpMethod(HTTP_DELETE).setAccessKey(accessKey).setAccessKeySecret(accessKeySecret).setRequestTimestamp(requestTime).setHost(server).setUri(uri).build();
WebClientOptions options = new WebClientOptions().setConnectTimeout(3000);
WebClient client = WebClient.create(vertx, options);
Future<HttpResponse<Buffer>> future = client.delete(port, host, uri).putHeader("content-type", CONTENT_TYPE_JSON).putHeader("Authorization", authorization).putHeader("x-ocp-date", rfc1123RequestTime).send();

依葫蘆畫瓢,一通百通。在調用返回信息里面有一個“traceId”,我們可以通過這個traceId在服務器端找到對應的日志信息。對于API失敗調試有一定的輔助作用。例如,執行刪除機型的返回如下:

==> 刪除新增的主機類型(1000010) ...
主機類型刪除成功。
{"duration" : 43,"server" : "b587654b4d","status" : 200,"successful" : true,"timestamp" : "2024-07-05T15:34:08.576+08:00","traceId" : "80070430b9814a99" ==>
}

對應OCP的日志信息:

### OCP日志位置
[admin@oat-ocp ocp]$ pwd
/home/admin/logs/ocp### 通過traceId為關鍵字搜索。
[admin@oat-ocp ocp]$ grep "80070430b9814a99" ocp-server.*
ocp-server.0.out:2024-07-05 15:34:08.555  INFO 9 --- [http-nio-0.0.0.0-8080-exec-2,80070430b9814a99,ce0c2accd19f] c.o.o.s.c.trace.RequestTracingAspect     : API: [DELETE /api/v2/compute/hostTypes/1000010?null, client=10.100.6.16, traceId=80070430b9814a99, method=NoDataResponse com.oceanbase.ocp.server.common.controller.ComputeController.deleteHostType(Long), args=1000010,]
ocp-server.0.out:2024-07-05 15:34:08.562  INFO 9 --- [http-nio-0.0.0.0-8080-exec-2,80070430b9814a99,ce0c2accd19f] c.o.o.c.h.service.HostTypeServiceImpl    : Deleted hostType: 1000010
ocp-server.0.out:2024-07-05 15:34:08.576  INFO 9 --- [http-nio-0.0.0.0-8080-exec-2,80070430b9814a99,ce0c2accd19f] c.o.o.s.c.trace.RequestTracingAspect     : API OK: [DELETE /api/v2/compute/hostTypes/1000010 client=10.100.6.16, traceId=80070430b9814a99, duration=43 ms]

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/41446.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41446.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/41446.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

linux下mysql的定時備份

備份是容災的基礎&#xff0c;是指為了防止系統出現操作或系統故障導致數據丟失&#xff0c;而將全部或部分數據集合從應用主機的硬盤或陣列復制到其他的存儲介質的過程為什么備份 硬件故障軟件故障誤操作病毒入侵保留歷史記錄災難性事件 存儲介質 光盤磁帶硬盤磁盤陣列DAS:直接…

[leetcode]文件組合

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<vector<int>> fileCombination(int target) {vector<vector<int>> vec;vector<int> res;int sum 0, limit (target - 1) / 2; // (target - 1) / 2 等效于 target /…

一些你可能不知道的前端小優化- ??(?????)

前言 以前寫css和html和一些原生DOM操作&#xff0c;感覺寫完就完事了。從來沒有考慮過一些性能優化的問題&#xff0c;剛好最近學完了瀏覽器的事件循環和瀏覽器的工作流程。今天大家分享一些我剛學習到的前端小優化。 瀏覽器的工作流程 瀏覽器的渲染過程大致分為以下幾個階…

Windows 11內置一鍵系統備份與還原 輕松替代Ghost

面對系統崩潰、惡意軟件侵襲或其他不可預見因素導致的啟動失敗&#xff0c;Windows 7~Windows 11內置的系統映像功能能夠迅速將您的系統恢復至健康狀態&#xff0c;確保工作的連續性和數據的完整性。 Windows內置3種備份策略 U盤備份&#xff1a;便攜且安全 打開“創建一個恢…

Ubuntu20.04突然沒網的一種解決辦法

本來要學一下點云地圖處理&#xff0c;用octomap庫&#xff0c;但是提示少了octomap-server庫&#xff0c;然后通過下面命令安裝的時候&#xff1a; sudo apt install ros-noetic-octomap-server 提示&#xff1a;錯誤:7 https://mirrors.ustc.edu.cn/ubuntu focal-security …

MWC上海展 | 創新微MinewSemi攜ME54系列新品亮相Nordic展臺

6月28日&#xff0c; 2024MWC上海圓滿落幕&#xff0c;此次盛會吸引了來自全球124個國家及地區的近40,000名與會者。本屆大會以“未來先行&#xff08;Future First&#xff09;”為主題&#xff0c;聚焦“超越5G”“人工智能經濟”“數智制造”三大子主題&#xff0c;探索討論…

leetcode熱題HOT42. 接雨水

一、問題描述&#xff1a; 給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖&#xff0c;計算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 二、解題思路&#xff1a; 思路1&#xff1a;通過動態規劃的預處理方式&#xff0c;分別計算每個柱子左右兩側的最大高度&…

js數據庫多級分類按樹形結構打印

可以使用 JavaScript 來按層級打印 categories 數組。首先&#xff0c;需要將這個數組轉換成一個樹形結構&#xff0c;然后再進行遞歸或者迭代來打印每個層級的內容。 以下是一個示例代碼&#xff0c;用來實現這個功能&#xff1a; const categories [{ id: 2, name: "…

java如何刪除字符串內部分字符

java中&#xff0c;如果要刪除字符串內部分字符&#xff0c;需要用delete方法&#xff0c;前提字符串是可變字符串StringBuffer類型的。 delete方法的語法格式是sbf.delete(start,end) 其中&#xff0c;sbf是任意StringBuffer對象&#xff0c;start是起始索引&#xff0c;end…

AQ mode

算法原理概述 AQ即adaptive quantization(自適應量化),屬于宏塊級別碼流分配的范疇,在一幀的宏塊之間調整碼率分配,x264中AQ算法的核心內容是:復雜宏塊使用大的QP,簡單宏塊使用小的QP。x264如何定義復雜?x264是根據宏塊內像素值的方差來評價宏塊復雜性,方差越大,宏塊…

溶解氧(DO)理論指南(1)

轉載自梅特勒官網資料&#xff0c;僅用于學習交流&#xff0c;侵權則刪&#xff01; 溶解氧理論指南 1 溶解氧(DO)原理1.1 溶解氧和分壓1.2 氧氣在水中的溶解度1.3 溶解氧對生物的重要性1.4 溶解氧對工業的重要性 1 溶解氧(DO)原理 氧是宇宙中第三大常見元素&#xff0c;也是…

JavaScript(6)——數據類型轉換

為什么需要類型轉換&#xff1f; JavaScript是弱數據類型&#xff1a;JavaScript不知道變量到底屬于哪種數據類型&#xff0c;只有賦值了才清除 使用表單&#xff0c;prompt獲取的數據默認為字符串類型&#xff0c;此時不能直接進行算數運算 隱式轉換 某些運算符被執行時&am…

力扣hot100-鏈表

文章目錄 概要鏈表的類型 題目&#xff1a;相交鏈表題解 概要 鏈表&#xff08;Linked List&#xff09;是數據結構中的一種&#xff0c;用于存儲具有線性關系的數據。在鏈表中&#xff0c;每個元素稱為一個節點&#xff08;Node&#xff09;&#xff0c;每個節點包含兩個部分…

”極大似然估計“和”貝葉斯估計“思想對比

極大似然估計&#xff08;Maximum Likelihood Estimation, MLE&#xff09;和貝葉斯估計&#xff08;Bayesian Estimation&#xff09;是統計學中兩種重要的參數估計方法&#xff0c;它們在思想和應用上有著顯著的差異。下面我將詳細對比這兩種方法的思想&#xff0c;并分別舉出…

兩次叛國投敵,沒有禍及子孫反而家族長盛不衰的傳奇

這個人就是韓國國王韓王信&#xff0c;漢朝八大異姓王之一。 第一次叛國投敵&#xff0c;發生在楚漢爭霸時期。有一次他的軍隊被項羽包圍&#xff0c;于是選擇了投降。不過&#xff0c;這是權宜之計&#xff0c;不久就借機回到劉邦陣營。 第二次叛國投敵&#xff0c;發生在西…

【Linux開發】基于ALSA庫實現音量調節

基于ALSA庫實現音量調節 ALSA庫實現音量調節1、使用alsamixer工具查看音頻接口2、完整代碼2.1、snd_mixer_open2.2、snd_mixer_attach、2.3、snd_mixer_selem_register2.4、snd_mixer_load2.5、snd_mixer_first_elem/snd_mixer_elem_next2.6、snd_mixer_selem_get_playback_vol…

linux下php的psr.so擴展源碼安裝

cd /usr/local/src git clone https://github.com/jbboehr/php-psr.git cd php-psr /usr/local/php/bin/phpize ./configure --with-php-config/usr/local/php/bin/php-config make make install在php.ini中添加extensionpsr.so 重啟php-fpm /etc/init.d/php-fpm relo…

打卡第3天---鏈表相關

除了每天自己寫博客總結我個人的學習收獲情況之外,我也會看其他錄友寫的博客文章,對于其他錄友的博客內容在代碼隨想錄的訓練營都是開誠布公的,都能互相看到。彼此學習,彼此參照,有一位錄友思路很清晰呀,用畫圖軟件把自己對題的思路畫的特別清晰,我 應該向他們學習;除此…

從零開始使用 Docsify 搭建文檔站點

引言 在當今的技術環境中&#xff0c;擁有一份易于訪問和美觀的文檔是至關重要的。Docsify 是一個非常適合快速搭建文檔站點的工具&#xff0c;它簡單易用&#xff0c;且不需要生成靜態文件。本文將帶你一步步從零開始使用 Docsify 搭建一個文檔站點。 1. 安裝 Node.js 和 np…

【ARMv8/v9 GIC 系列 5.1 -- GIC GICD_CTRL Enable 1 of N Wakeup Function】

請閱讀【ARM GICv3/v4 實戰學習 】 文章目錄 GIC Enable 1 of N Wakeup Function基本原理工作機制配置方式應用場景小結GIC Enable 1 of N Wakeup Function 在ARM GICv3(Generic Interrupt Controller第三代)規范中,引入了一個名為"Enable 1 of N Wakeup"的功能。…