
# HBase REST API接口介绍
MRS1.6之后，支持采用REST的方式来对HBASE进行相应的业务操作，REST API支持curl命令和Java client来操作HBase，有关curl命令的详细使用方法与Apache HBase保持一致，具体请参见<https://hbase.apache.org/book.html#_rest>。
![](https://support.huaweicloud.com/devg-mrs/public_sys-resources/note_3.0-zh-cn.png)
由于当前默认使用 SSL protocols 为 TLSv1.1,TLSv1.2，所以在启用CURL调用 REST 时需判断当前环境支持的 SSL protocols。
#### 使用curl命令
- 未开启Kerberos认证集群 在未开启Kerberos认证的集群中执行curl命令时增加以下参数。例如，
  ```
  curl -vi -k POST -H "Accept: text/xml"   -H "Content-Type: text/xml" -d '<?xml version="1.0" encoding="UTF-8"?> <TableSchema name="users"><ColumnSchema name="cf" /> </TableSchema>' "https://<HBase安装RESTServer服务的节点Ip>:21309/users/schema"
  ```
  
- 开启Kerberos认证的安全集群 在安全集群中执行curl命令时，请遵循以下步骤：
  1. 进行kerberos认证。例如， 人机用户：*kinit* *MRS* *集群用户*
     例如：**kinit hbaseuser**
     机机用户：*kinit -kt 认证凭据路径* *MRS* *集群用户*
     例如：**kinit -kt /opt/user.keytab hbaseuser**
     
  
  2. 在curl命令中需在请求类型之前添加--negotiate -u：参数。例如，
     ```
     curl -vi -k --negotiate -u: POST -H "Accept: text/xml"   -H "Content-Type: text/xml" -d '<?xml version="1.0" encoding="UTF-8"?> <TableSchema name="users"><ColumnSchema name="cf" /> </TableSchema>' "https://<HBase安装RESTServer服务的节点Ip>:21309/users/schema"
     ```
     
   
 
#### 使用Java Client
使用Java调用REST API，请按照以下步骤。（可参见样例代码中RestExample部分代码）。
1. 进行kerberos认证(未开启Kerberos认证集群可以跳过此步骤)
2. 创建一个org.apache.hadoop.hbase.rest.client.Cluster类的集群对象，通过调用集群类的add方法和REST server的集群IP和端口来添加集群。
   ```
   Cluster cluster = new Cluster();
   cluster.add("10.10.10.10:21309");
   ```
   
3. 使用在步骤2中添加的集群初始化类"org.apache.hadoop.hbase.rest.client.Client"的客户端对象，调用doAs来操作HBase。
   ```
   Client client = new Client(cluster, true);
   ```
   ```
   UserGroupInformation.getLoginUser().doAs(new PrivilegedAction() {
     public Object run() {
       
       // Rest client code
       
       /* Sample code to list all the tables
          client.get("/")
       */
       return null;
     }
   });
   ```
   
4. 可以参考如下的使用方式来了解如何调用不同的Rest API。
- **使用纯文本的方式获取命名空间**
1. 以包含命名空间的路径作为参数，使用client去调用get方法获取命名空间。响应将被"org.apache.hadoop.hbase.rest.client.Response"类的对象捕获。例如 :
   ```
   Response response;
   String namespacePath = "/namespaces/" + "nameSpaceName";
   response = client.get(namespacePath);
   System.out.println(Bytes.toString(response.getBody()));
   ```
   
- **创建或修改命名空间**
1. 在创建或修改命名空间时，都是使用NamespacesInstanceModel创建模型并使用buildTestModel()方法构建模型，如下所示。这里创建模型，使模型包含要创建的命名空间的属性信息。
   ```
   Map<String, String> NAMESPACE1_PROPS = new HashMap<String, String>();
   NAMESPACE1_PROPS.put("key1", "value1");
   NamespacesInstanceModel model = buildTestModel(NAMESPACE1,NAMESPACE1_PROPS);
   private static NamespacesInstanceModel buildTestModel(String namespace, Map<String, String> properties) {
   NamespacesInstanceModel model = new NamespacesInstanceModel();
   for (String key : properties.keySet()) {
   model.addProperty(key, properties.get(key));
   }
   return model;
   }
   ```
   ![](https://support.huaweicloud.com/devg-mrs/public_sys-resources/note_3.0-zh-cn.png)
   在使用POST/PUT请求创建/修改表时，TableSchemaModel是用来创建模型的类。
   
2. 检查以下步骤以了解如何使用不同的方式创建和修改命名空间。
- **使用xml的方式创建命名空间**
1. 在使用NamespacesInstanceModel创建模型后，以包含命名空间的路径，内容类型（调用类为'org.apache.hadoop.hbase.rest.Constants'，这里调用的参数为Constants.MIMETYPE_XML）和内容（在这里需要将内容转换为xml，使用下面显示的toXML()方法）作为参数，使用client去调用post方法创建命名空间。响应将被'org.apache.hadoop.hbase.rest.client.Response'类的对象捕获。例如 ：
   ```
   Response response;
   String namespacePath = "/namespaces/" + "nameSpaceName";
   response = client.post(namespacePath, Constants.MIMETYPE_XML, toXML(model));
   private static byte[] toXML(NamespacesInstanceModel model) throws JAXBException {
   StringWriter writer = new StringWriter();
   context.createMarshaller().marshal(model, writer);
   return Bytes.toBytes(writer.toString());
   }
   ```
   
2. 在使用xml方式进行Get请求时，可使用如下所示的fromXML()方法，从响应中获取模型，并从模型中获取创建的命名空间的名称。
   ```
   private static <T> T fromXML(byte[] content) throws JAXBException {
   return (T) context.createUnmarshaller().unmarshal(new ByteArrayInputStream(content));
   }
   ```
   
- **使用json的方式修改命名空间**
1. 在使用NamespacesInstanceModel创建模型后，调用客户端类的put方法来创建命名空间，参数包含命名空间的路径，内容类型（调用类为org.apache.hadoop.hbase.rest.Constants，这里调用的参数为Constants.MIMETYPE_JSON）和内容（在这里需要转换内容到json，使用jsonMapper作为参数）。响应被'org.apache.hadoop.hbase.rest.client.Response'类的对象捕获。例如 ：
   ```
   ObjectMapper jsonMapper = new JacksonProvider().locateMapper(NamespacesInstanceModel.class, MediaType.APPLICATION_JSON_TYPE);
   Response response;
   String namespacePath = "/namespaces/" + "nameSpaceName";
   String jsonString = jsonMapper.writeValueAsString(model);
   response = client.put(namespacePath, Constants.MIMETYPE_JSON, Bytes.toBytes(jsonString));
   ```
   
2. 在使用json方式进行Get请求时，jsonMapper具有如下所示的readValue()方法，用于从响应中获取模型，并能从模型中获取创建的命名空间。
   ```
   jsonMapper.readValue(response.getBody(), NamespacesInstanceModel.class);
   /*Here second argument should be according to API, if its     **related to table it should be TableSchemaModel.class*/
   ```
   
- **使用protobuf的方式修改命名空间**
1. 在使用NamespacesInstanceModel创建模型后，调用客户端类的put方法来创建命名空间，其参数包含命名空间路径，内容类型（调用类为org.apache.hadoop.hbase.rest.Constants'，这里调用的参数为Constants.MIMETYPE_PROTOBUF）和内容（需要转换的内容如下所示，使用createProtobufOutput来创建protobuf）。响应将被'org.apache.hadoop.hbase.rest.client.Response'类的对象捕获。例如 ：
   ```
   Response response;
   String namespacePath = "/namespaces/" + "nameSpaceName";
   response = client.put(namespacePath, Constants.MIMETYPE_PROTOBUF, model.createProtobufOutput());
   model.getObjectFromMessage(response.getBody());
   ```
   
2. 在使用protobuf的方式进行Get请求时，可使用如下所示的 getObjectFromMessage 方法，用于从响应中获取模型，并从模型中获取创建的命名空间。
   ```
   model.getObjectFromMessage(response.getBody());
   ```
   
 
