facebook/swift:构建thrift http server(1)

如何基于facebook/swift构建一个支持HTTP访问的thrift服务?说来话长。我将用分几篇博客介绍这个问题的解决思路和具体实现。

背景说明

我有一个项目facelog,是基于facebook/swift框架(java)开发的。在实际的项目应用时,需要从浏览器端能调用facelog的接口方法,要实现这个功能,一个笨办法就是专门写一个java web应用,相当于一个二传手,对浏览器需要访问的facelog方法,提供GET/POST调用接口供浏览器调用,现在我们就是这么干的,这么做无疑增加了开发工作量,能不能让浏览器直接调用facelog服务的接口方法呢?
如果能这样实现将好处多多:
不需要java web应用设计作为转发用途的POST/GET接口,减少了开发工作量同时也减少了系统的响应延迟及复杂度。

Node.js方案

facebook/swift是基于thrift的java平台的RPC框架。thrift是一种支持广泛开发语言的RPC框架,自然也是支持javascript访问的。
thrift的官方网站的《Javascript Tutorial》详细介绍了如何用在浏览器上用javascript访问thrift服务。参照这个教程可以就可以构建一个node.js服务,浏览器则通过javascript访问node.js提供的thrift接口,在这个tutor中,前端使用javascript,服务端则是用Node.js实现的。

所以参照上面的教程在浏览器上用javascript访问facelog服务是完全可以实现的。然而仔细评估之后,觉得《Javascript Tutorial》提供的这个方案对于我的facelog项目并不是最佳解决方案,原因嘛,总得来说就是更麻烦,如下:

  1. 开发工作量更大
    《Javascript Tutorial》方案中,后端是一个node.js服务。而facelog是一个java平台的服务。如果采用这个方案,我需要重写一个node.js服务作为代理服务转所有的HTTP请求到facelog(java)。对于拥有100多个接口方法的facelog服务,再重写一个一样的node.js转发服务也是不小的工作量,这同样增加了项目的复杂度和系统响应延迟,后续维护的工作量也相应增加。
  2. 部署运维更复杂
    facelog(java)的部署很简单,系统依赖很简单,只需要java虚拟机就可以在命令行直接运行,如果增加一个node.js服务,就需要多一个node的运行平台。对于项目部署和运维都增加了难度和工作量。

所以对于我来说,理想的方案就是运行一个支持XHR(XML Http Request)访问的facelog(java)服务,它占用一个新的端口号,web端通过javascript用浏览器的XMLHttpRequest对象直接调用这个XHR服务。这样对于facelog来说只是增加一个新的端口号而已,新的XHR服务还是在java平台运行。没有中间商赚差价,web端的系统响应迟延与java client是一样的。

TServlet方案

那么thrift的java框架有没有提供HTTP访问能力呢?答案是有的。
请关注org.apache.thrift.server.TServlet这个类。
下面是TServlet的部分代码

public class TServlet extends HttpServlet {
	private final TProcessor processor;
	private final TProtocolFactory inProtocolFactory;
	private final TProtocolFactory outProtocolFactory;
	private final Collection<Map.Entry<String, String>> customHeaders;

	public TServlet(TProcessor processor, TProtocolFactory inProtocolFactory, TProtocolFactory outProtocolFactory) {
		this.processor = processor;
		this.inProtocolFactory = inProtocolFactory;
		this.outProtocolFactory = outProtocolFactory;
		this.customHeaders = new ArrayList<Map.Entry<String, String>>();
	}

	public TServlet(TProcessor processor, TProtocolFactory protocolFactory) {
		this(processor, protocolFactory, protocolFactory);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		TIOStreamTransport inTransport = null;
		TIOStreamTransport outTransport = null;
		try {
			TIOStreamTransport transport;
			response.setContentType("application/x-thrift");
			if (null != this.customHeaders) {
				for (Map.Entry<String, String> header : this.customHeaders) {
					response.addHeader(header.getKey(), header.getValue());
				}
			}
			ServletInputStream in = request.getInputStream();
			ServletOutputStream out = response.getOutputStream();
			inTransport = transport = new TIOStreamTransport((InputStream) in, (OutputStream) out);
			outTransport = transport;
			TProtocol inProtocol = this.inProtocolFactory.getProtocol((TTransport) inTransport);
			TProtocol outProtocol = this.outProtocolFactory.getProtocol((TTransport) outTransport);
			this.processor.process(inProtocol, outProtocol);
			out.flush();
		} catch (TException te) {
			throw new ServletException((Throwable) te);
		}
	}

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		this.doPost(request, response);
	}
}

如果你熟悉thrift,在TServlet类的代码中看到TProcessorTProtocol类就明白,这个类继承自javax.servlet.http.HttpServlet,可以将一个thrift接口服务(TProcessor)封装为一个Servlet。有了Servlet,就可以在所有支持Servlet的web容器(比如tomcat)上运行thrift服务了.

当初看到这个类,我好一阵兴奋,庆幸自己这么容易就找到了答案。但深入了解之后,得出一个令人沮丧的结论,TServlet方案也不是适合我的方案。

  1. TProcessorThriftServiceProcessor
    对,org.apache.thrift.TProcessorcom.facebook.swift.service.ThriftServiceProcessor,前一个是thrift(java)定义的接口,后者则是facebook/swift定义的接口,我的facelog项目基于facebook/swift设计,服务接口封装为ThriftServiceProcessor实例,并不能直接作为参数被TServlet封装为Servlet
  2. 额外的Servlet容器
    就算想办法将ThriftServiceProcessor封装为TProcessor丢进TServlet封装为Servlet,也需要tomcat这样的Servlet容器才能运行。原本facelog只需要一个standalone的jar包就能在JVM上运行,项目部署极简单,现在凭空多了个tomcat,配置运行tomcat对于项目部署运维就增加了很多的工作量,所以tomcat对于我来说太重了。
    那么jetty呢?Jetty 是一个开源的servlet容器,可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行(stand-alone)的Java应用提供网络和web连接。但同样要增加一些依赖包不是么?我对jetty并不熟悉,为了解决问题学习jetty的成本也要考虑进去。风险也不小。

Netty http server

这也不行,那也不行,你到底要闹哪样啊?
不想增加tomcat,甚至不想增加额外的依赖库,只基于facebook/swift实现一个XHR服务,让浏览能直接访问thrift服务接口。
对,这就是我的最理想的方案。
太晚了,写不下去了。
请看我的下一篇博客。

《facebook/swift:构建thrift http server(2)–HttpServerCodec》
《facebook/swift:构建thrift http server(3)–CORS跨域》
《facebook/swift:构建thrift http server(4)–ThriftXHRDecoder,ThriftXHREncoder》

<think>嗯,用户这次的问题是关于HiveServer2的,还提到了hbase找不到,以及启动HiveServer2时的输出。我需要先理解用户的需求。首先,用户可能是在尝试启动HiveServer2时遇到了问题,或者他们想了解HiveServer2的基本信息。输出中的“which: no hbase”可能让他们困惑,虽然这可能和当前问题无关,但需要解释清楚。 首先,我应该介绍HiveServer2是什么,它的作用,以及为什么在Hadoop生态系统中重要。然后,用户提到的错误信息中找不到hbase,这可能是因为hbase没有安装或者没有添加到PATH环境变量中,但用户当前的问题是关于HiveServer2的,所以需要指出这一点,避免混淆。 接下来,用户提供的启动日志显示HiveServer2正在启动,并生成了会话ID,这可能意味着启动成功,但需要进一步确认。可能用户不确定启动是否正常,或者遇到了其他问题。这时候应该引导他们检查日志,确认服务是否正常运行,比如通过查看日志文件或使用netstat检查端口。 然后,我需要分步骤解释如何启动和验证HiveServer2,包括启动命令、检查进程、查看端口等。同时,用户可能遇到的问题如端口冲突、权限问题、依赖服务未启动(如Hadoop、YARN)也需要提到,并给出相应的解决建议。 关于hbase未找到的问题,虽然可能不影响HiveServer2,但需要简要说明可能的原因,比如环境变量配置问题或未安装,并提供检查方法,比如检查PATH变量或安装hbase。 最后,总结用户可能需要进一步检查的地方,确保他们能自行排查问题。还要注意使用中文,结构清晰,避免技术术语过于复杂,让用户容易理解。</think>--- ### **1. HiveServer2 简介** **HiveServer2** 是 Apache Hive 提供的一个服务进程,主要用于支持多客户端并发访问 Hive 数据仓库。通过 HiveServer2,用户可以使用 JDBC/ODBC 驱动、Beeline CLI 或其他工具远程执行 Hive 查询,并支持身份验证和权限管理。 #### **核心功能** - **远程访问**:允许客户端通过 Thrift 协议(默认端口 `10000`)远程提交 HiveQL 查询。 - **并发支持**:提供会话管理和查询隔离,支持多用户并发操作。 - **安全增强**:支持 Kerberos 认证、LDAP 集成和基于角色的访问控制(RBAC)。 - **兼容性**:与 Hive CLI(旧版命令行)相比,HiveServer2 更稳定且功能更丰富。 --- ### **2. 您当前的操作分析** #### **(1) 关于 `which: no hbase` 的提示** - 该提示表明您的系统环境变量 `PATH` 中未找到 `hbase` 命令,但 **这与启动 HiveServer2 无关**。HiveServer2 的运行不依赖 HBase,除非您的 Hive 配置中集成了 HBase 作为存储引擎。 - 如果需使用 HBase,需单独安装并配置环境变量。 #### **(2) HiveServer2 启动日志解读** ```plaintext 2025-03-04 21:49:02: Starting HiveServer2 Hive Session ID = a1c160de-5f9a-43e8-ac62-a36d6774cdaa Hive Session ID = d3aba010-103f-4901-bc21-19dd37aabf08 ``` - 日志显示 HiveServer2 已启动,并生成了两个会话 ID(可能因客户端连接触发)。 - **需进一步确认服务是否真正启动成功**:检查端口监听状态或查看完整日志。 --- ### **3. HiveServer2 启动验证** #### **(1) 检查服务进程** ```bash # 查看 HiveServer2 进程是否存在 ps -ef | grep HiveServer2 ``` - 正常输出应包含 `HiveServer2` 进程信息,例如: ```plaintext hive 12345 1 ... org.apache.hive.service.server.HiveServer2 ``` #### **(2) 检查端口监听** ```bash # 确认 10000 端口是否处于监听状态 netstat -tuln | grep 10000 ``` - 正常输出示例: ```plaintext tcp6 0 0 :::10000 :::* LISTEN ``` #### **(3) 使用 Beeline 连接测试** ```bash # 使用 Beeline 客户端连接 HiveServer2 beeline -u "jdbc:hive2://localhost:10000" -n <用户名> ``` - 连接成功后,执行 `show databases;` 验证查询功能。 --- ### **4. 常见问题及解决** #### **(1) 启动失败的可能原因** - **依赖服务未启动**:Hadoop HDFS/YARN 未运行。 - **端口冲突**:`10000` 端口被其他进程占用。 - **元数据库问题**:Hive 的元数据库(如 MySQL)连接失败。 - **权限不足**:Hive 数据目录(如 `/user/hive/warehouse`)权限错误。 #### **(2) 日志定位问题** HiveServer2 的详细日志位于: ```bash # 默认日志路径 tail -f /tmp/<用户名>/hive.log # 或配置的日志目录(如 /opt/module/hive/logs) ``` --- ### **5. 总结** - 当前日志显示 HiveServer2 已尝试启动,但需通过 **进程检查、端口监听、客户端连接** 进一步验证。 - 若遇到启动失败,优先检查: 1. Hadoop 集群是否正常运行。 2. Hive 元数据库配置(如 `jdbc://mysql://...`)。 3. 日志中的 `ERROR` 或 `WARN` 信息。 如需更具体的帮助,请提供完整的 HiveServer2 启动日志或错误提示。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值