本文梳理的Rest API主要是针对Web端的Rest API,暂不包括处理Agent 请求的API.该部分的处理以后会补充。
1.基础知识准备
1.1.IDEA远程调试Ambari-Server
为了查看追踪Ambari-Server对Rest API的处理过程,可以采用Debug方式启动Ambari-Server,然后使用本地IDEA环境连接Ambari-Server,对Ambari-Server进行远程调试,追踪Ambari-Server的运行流程。
主要操作步骤如下:
① 在IDEA中配置远程服务器;
② 以Debug模式启动Ambari-Server;
③ 在IDEA中连接Ambari-Server,开始追踪Server运行流程。
下面对各个步骤进行详细说明。
1.1.1.在IDEA中配置远程服务器
操作步骤:
① 在工具栏中,点击“Select Run/Debug Configuration”按钮;
② 在弹出菜单中点击“Edit Configurations…”,弹出“Run/Debug Configurations”对话框;
③ 在弹出“Run/Debug Configurations”对话框中选择点击添加按钮,添加类型为”Remote”;
④ 配置Remote Server,然后点击”OK”,保存配置Remote Server;
配置完成后,IDEA工具栏会显示刚才配置的Server
1.1.2.以Debug模式启动Ambari-Server
Ambari-Server后端使用postgreSQL数据库时,启动命令为:
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91-2.6.2.3.el7.x86_64/bin/java -server -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=5005 -XX:NewRatio=3 -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -Dsun.zip.disableMemoryMapping=true -Xms512m -Xmx2048m -XX:MaxPermSize=128m -Djava.security.auth.login.config=/etc/ambari-server/conf/krb5JAASLogin.conf -Djava.security.krb5.conf=/etc/krb5.conf -Djavax.security.auth.useSubjectCredsOnly=false -cp /etc/ambari-server/conf:/usr/lib/ambari-server/*:/usr/share/java/postgresql-jdbc.jar org.apache.ambari.server.controller.AmbariServer
Ambari-Server后端使用Mysql数据库时,还需要进一步配置。
操作步骤如下:
① 拷贝mysql驱动,执行命令:cp /usr/share/java/mysql-connector-java.jar /var/lib/ambari-server/resources/
② 编辑vim /etc/ambari-server/conf/ambari.properties文件,增加属性:server.jdbc.driver.path=/usr/share/java/mysql-connector-java.jar
③ 使用如下命令启动Ambari-Server。
/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.91-2.6.2.3.el7.x86_64/bin/java -server -Xdebug -Xrunjdwp:transport=dt_socket,suspend=n,server=y,address=5005 -XX:NewRatio=3 -XX:+UseConcMarkSweepGC -XX:-UseGCOverheadLimit -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -Dsun.zip.disableMemoryMapping=true -Xms1012m -Xmx3048m -XX:MaxPermSize=256m -Djava.security.auth.login.config=/etc/ambari-server/conf/krb5JAASLogin.conf -Djava.security.krb5.conf=/etc/krb5.conf -Djavax.security.auth.useSubjectCredsOnly=false -cp /etc/ambari-server/conf:/usr/lib/ambari-server/*:/usr/share/java/mysql-connector-java.jar org.apache.ambari.server.controller.AmbariServer
1.1.3.在IDEA中连接Ambari-Server
操作步骤:
① 在程序中相应位置填上断点;
② 服务器启动后,立马在IDEA中开启调试:
1.2.Rest API 说明
所谓Rest,就是用URL定位资源,用HTTP动词(GET,POST,DELETE,DETC)描述操作,主要特点有:
① REST描述的是在网络中client和server的一种交互形式;REST本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口);
② Server提供的RESTful API中,URL中只使用名词来指定资源,原则上不使用动词。“资源”是REST架构或者说整个网络处理的核心。如:
a)http://api.qc.com/v1/friends: 获取某人的好友表;
b)http://api.qc.com/v1/profile: 获取某人的详细信息;
③ 用HTTP协议里的动词来实现资源的添加,修改,删除等操作。即通过HTTP动词来实现资源的状态扭转:
a)GET 用来获取资源;
b)POST 用来新建资源(也可以用于更新资源);
c)PUT 用来更新资源,DELETE 用来删除资源。
比如:DELETE http://api.qc.com/v1/friends: 删除某人的好友 (在http parameter指定好友id)
POST http://api.qc.com/v1/friends: 添加好友
④ Server提供的RESTful API中,URL中只使用名词来指定资源,原则上不使用动词。“资源”是REST架构或者说整个网络处理的核心。
⑤ Server和Client之间传递某资源的一个表现形式,比如用JSON,XML传输文本,或者用JPG,WebP传输图片等。当然还可以压缩HTTP传输时的数据(on-wire data compression)。
用 HTTP Status Code传递Server的状态信息。比如最常用的 200 表示成功,500 表示Server内部错误等。
1.2.1.使用curl发送Rest API请求
curl是很方便的Rest客戶端,可以很方便的完成许多Rest API测试的需求,甚至,如果是需要先登入或认证的rest api,也可以进行测试,利用curl指令,可以送出HTTP GET, POST, PUT, DELETE, 也可以改变 HTTP header來满足使用REST API需要的特定条件。
curl参数很多,这里仅列出测试Rest时需要用到的。
curl后面加的url加引号也可以,不加引号也可以,如果有非纯英文字或数字外的字元,不加引号可能会有问题,如果是经过编码的url,也要加上引号。
(2)HEADER
在http header加入信息,如:curl -v -i -H “Content-Type: application/json” http://www.example.com/users
(3)HTTP Parameter
http參數可以直接加在url的query string,也可以用-d帶入參數間用&串接,或使用多個-d,例如:
# 使用`&`串接多个参数
curl -X POST -d "param1=value1¶m2=value2"
# 也可使用多個`-d`,效果同上
curl -X POST -d "param1=value1" -d "param2=value2"
(4)post json 格式的资料
如同时需要传送request parameter和json,request parameter可以加在url后面,json数据则放入-d的参数,然後利用单引号將json资料含起來(如果json內容是用单引号,-d的参数則改用单引号包裹),header要加入”Content-Type:application/json”跟”Accept:application/json”
curl http://www.example.com?modifier=kent -X PUT -i -H "Content-Type:application/json" -H "Accept:application/json" -d '{"boolean" : false, "foo" : "bar"}'
# 不加"Accept:application/json"也可以
curl http://www.example.com?modifier=kent -X PUT -i -H "Content-Type:application/json" -d '{"boolean" : false, "foo" : "bar"}'
(5)HTTP Basic Authentication
如果网站是采用HTTP基本认证, 可以使用 –user username:password 登入,例如:curl -i –user kent:secret http://www.rest.com/api/foo’
1.2.2.Ambari-Server中基本的Rest API请求举例
(1)认证
对Ambari API操作需要认证,在Ambari中采用的HTTP基本认证,该认证可使用-u或是–user参数指定,例如:curl –user name:password http://{your.ambari.server}/api/v1/clusters
(2)监控
Ambari API提供监控Hadoop集群运行状况和metrics信息的接口。例子:获取c1集群中HDFS服务的DataNode组件资源信息。
请求:GET /clusters/c1/services/HDFS/components/DATANODE
响应:
200 OK
{
"href" : "http://your.ambari.server/api/v1/clusters/c1/services/HDFS/components/DATANODE",
"metrics" : {
"process" : { "proc_total" : 697.75, "proc_run" : 0.875},
"rpc" : {...},
"ugi" : {...},
"dfs" : {"datanode" : {...}},
"disk" : {...},
"cpu" : {...}
...
},
"ServiceComponentInfo" : {
"cluster_name" : "c1",
"component_name" : "DATANODE",
"service_name" : "HDFS"
"state" : "STARTED"
},
"host_components" : [
{
"href" : "http://your.ambari.server/api/v1/clusters/c1/hosts/host1/host_components/DATANODE",
"HostRoles" : {"cluster_name" : "c1","component_name" : "DATANODE","host_name" : "host1"}
}
]
}
(3)管理
Ambari API提供了对Hadoop集群资源管理的方法,包括资源创建、删除和更新。例如
创建HDFS服务,请求:POST /clusters/c1/services/HDFS;响应:201 Created。
启动服务,请求:PUT /clusters/c1/services/HDFS/,传入body: {“serviceInfo”:{”state”:”STARTED”} };
响应:202 Accepted。
1.4.Ambari-Server中基本资源对象与Provider
2.Ambari-Server 处理Rest API基本流程说明
下面以查看集群中主机列表API为例,说明Ambari-Server处理Rest API的基本处理框架。该API的具体形式为:get: api/v1/clusters/mycluster/hosts。
说明:Ambari-Server中嵌入Jetty,使用Jetty处理Web请求,关于Jetty对请求的处理及Jetty原理框架背景知识见文档“Jetty框架调研报告”。
2.1.从Server到Handler
Ambari-Server在收到Web请求后,转入到Jetty Hander逻辑中,由Jetty Hander进行处理。这个过程可以用标准的Jetty Server处理图表示。
Ambari-Server注册的处理Rest API请求的Hander为HandlerCollection类型,实际子类为AmbariHandlerList,该Hander的处理逻辑为:不断遍历注册的子Handler,直到找到一个可以处理该请求的子Hander,该Handler处理该请求,重置请求的处理位,如果遍历完毕还没有找到,则抛出异常,表示无法处理该请求。
该Handler的handler方法处理逻辑如下:
其中processHandlers处理过程如下:
2.2.Hander分派
Ambari-Server使用Jersey框架作为JAX-RS标准的实现。具体的资源及资源方法通过JAX-RS标注进行标识。Ambari-Server将org.apache.ambari.server.api.services包下所有类都通过Jersey注册成Jetty Handler。
ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
"com.sun.jersey.api.core.PackagesResourceConfig");
sh.setInitParameter("com.sun.jersey.config.property.packages",
"org.apache.ambari.server.api.rest;" +
"org.apache.ambari.server.api.services;" +
"org.apache.ambari.eventdb.webservice;" +
"org.apache.ambari.server.api");
sh.setInitParameter("com.sun.jersey.api.json.POJOMappingFeature", "true");
root.addServlet(sh, "/api/v1/*");
因此,在找某个Rest API的处理Handler时,可直接进行Rest API的URI进行标注对比。对于get:api/v1/clusters/mycluster/hosts URI请求的Handler,可直接找标注了@path(/clusters/)的类,该类为ClusterService,并找到URI路径全匹配的Get方法,最终找到getHostHandler方法,该方法返回一个JAX-RS子资源,表明对该Get请求由HostService的相应方法进行处理响应。
@Path("{clusterName}/hosts")
public HostService getHostHandler(@Context javax.ws.rs.core.Request request, @PathParam("clusterName") String clusterName) {
return new HostService(clusterName);
}
同理,在HostService中按照路径匹配规则找到响应的处理方法,方法为:getHosts。
@GET
@Produces("text/plain")
public Response getHosts(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
return handleRequest(headers, body, ui, Request.Type.GET,
createHostResource(m_clusterName, null, ui));
}
在Ambari-Server中,几个常用的Service列表如下:
2.3.具体Handler处理
AmbariHandlerList在将Rest API请求进行转发时,首先转发给一级JAX-RS资源的相关方法,如果该JAX-RS资源能直接处理,则直接调用BaseSevrvice类的handleRequest方法进行请求处理,否则转发给二级JAX-RS资源,由该JAX-RS资源处理,处理方式相同(要么直接调用BaseService.handleRequest方法或是继续转给下一级资源)。
BaseService对请求的处理逻辑过程如下:
在Ambari中,Request(org.apache.ambari.server.api.services)分为:GetRequest,PostRequest,PutRequest,DeleteRequest,QueryPostRequest 5中Request。5中Request的类关系如下:
Request.process方法调用的是BaseRequest类中的process方法,该方法的主要处理步骤如下所示:
① 调用函数parseRenderer();//不知道具体干什么的
② 调用函数parseQueryPredicate();//不知道具体干什么的
③ 调用Request的Hander的handleRequest函数继续处理请求并返回结果;
④ 如果处理结果不为Error,这对结果进行初步解析,并返回处理结果。
不同的Request的实现代码基本相同,也都比较简单,对Request的主要处理逻辑都在BaseRequest里。但是不同的Request的Handler不同,如GetRequest的Handler为ReadHandler(org.apache.ambari.server.api.handlers)。GetRequest的类实现代码如下:
public class GetRequest extends BaseRequest {
public GetRequest(HttpHeaders headers, RequestBody body, UriInfo uriInfo, ResourceInstance resource) {
super(headers, body, uriInfo, resource);
}
@Override
public Type getRequestType() {
return Type.GET;
}
@Override
protected RequestHandler getRequestHandler() {
return new ReadHandler();
}
}
ReadHandler的handleRequest函数做真正的请求处理工作,ReadHandler.handlerRequest的主要处理步骤如下:
Clustercontroler查选资源列表的方式为向资源Provider进行查询。对于查询Host列表请求,对应的资源Provider为HostResourceProvider。HostResourceProvider在获取资源列表时,首先通过AmbarManagementController(org.apache.server.controller.AmbariManagementControllerImp)获取Request对应的集群Clusters(org.apache.ambari.server.state.cluster.ClustersImpl),Clusters实例在Ambari-Server启动时初始化,其中存储了相应的host列表;
2.4.基本流程总结