通过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.mzph.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"的功能。…