1.生产场景
生产场景中,有一个PHP后台程序负责采集用户访问门户的数据,之前采用的是piwik+MySQL的采集存储架构,后来投产后,发现每天数据量将近30万条之多!!!显然,原生的mysql是跑不动了。而kafka又不提供php接口,所以将采集存储方案转换为了restful接口的方案。
2.需求
php采集程序,通过post请求将json数据格式发至该restful接口,负责提供该接口的程序,接收到该post请求后,解析该json数据,通过协商好的各字段值,和Hbase交互,执行该数据的增改删操作,并将该数据操作的结果封装成json返回给php采集程序。
3.基本常识
- Java异常信息保存的一个简单方法
- Web Serveice百度百科
- 四种常见的 POST 提交数据方式
- 将数据封装为Json数据格式
- json-lib....jar 架包 jsonObject介绍
- java 各种类型数据,集合对象封装 成json
关于Json的jar包有很多,Php采集程序post的json数据被转换为JSONObject格式,但经测试发现,如果导入的是org.json.JSONObject jar包是无法成功接收到的,需改用net.sf.json.JSONObject。前者与后者在JSONObject化的方法上还是有区别的。比如我有如下json类型的数据:
data={"id":1,"content":"Hello, World!"}
org.json.JSONObject将之转换为JSONObject,是通过如下方式:
JSONObject dataObj=new JSONObject(data),此时dataObj即为data转换后的JSONObject格式。
但是net.sf.json.JSONObject用之即会报错,它实现的方式如下:
JSONObject dataObj = JSONObject.fromObject(data);
需要注意一下。
4.环境部署
- WIN7系统JavaEE(java+tomcat7+Eclipse)环境配置
- 修改tomcat默认的编码方式
- Linux下安装Tomcat服务器和部署Web应用
- 修改tomcat端口号
- 手把手图文教你eclipse下如何配置tomcat
- windows cmd窗口下tomcat关闭和重启的命令是什么?
- 搭建一个RESTFUL风格的Web Service (Maven版本)
- eclipse构建及运行maven web项目
- eclipse 创建maven 项目 动态web工程完整示例
- Eclipse+Maven创建webapp项目
- 如何用Maven创建web项目(具体步骤)
按照上述文档,可能由于Maven版本等问题,可能会出现步骤展现不一致现象,试着通过如下三篇文章解决 - (转)利用Eclipse创建maven项目并生成META-INF和WEB-INF目录
- web.xml is missing and is set to true[解决]
- maven项目转web项目时Java Build path entrles里没有内容
5.设计方案
①Jersey框架
用Jersey开发RESTful服务
com.sun.jersey.api.Container.ContainerException
Web编程学习四: 使用Jersey来创建RESTful WebService
②Spring框架
Spring3 MVC 注解(一)---注解基本配置及@controller和 @RequestMapping 常用解释
使用spring框架实现RESTful
SpringMVC写REST接口:第二篇 配置Maven的pom.xml文件
③Java与Hbase交互
Hbase常用操作(增删改查)
JAVA连接HBase
public HBaseCommonUtil(String rootDir,String zooKeeperAddress,String clientPort) {
HBASE_CONFIG = new Configuration();
HBASE_CONFIG.set("hbase.rootdir", rootDir);
HBASE_CONFIG.set("hbase.zookeeper.quorum", zooKeeperAddress);
HBASE_CONFIG.set("hbase.zookeeper.property.clientPort", clientPort);
conf = HBaseConfiguration.create(HBASE_CONFIG);
try {
conn = ConnectionFactory.createConnection(conf);
hbaseAdmin = (HBaseAdmin) conn.getAdmin();
} catch (IOException e) {
e.printStackTrace();
}
}
新增操作
//Hbase新增操作
public void insertData(String tableName,String rowKey,String column,String value) {
try {
HTable table = new HTable(conf, tableName);
Put put = new Put(Bytes.toBytes(rowKey));
put.add(Bytes.toBytes("detail"), Bytes.toBytes(column), Bytes.toBytes(value));
table.put(put);
table.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
删除操作
//Hbase删除操作
public void deleteData(String tableName, String rowKey) throws IOException {
HTable table;
table = new HTable(conf, tableName);
List list = new ArrayList();
Delete del = new Delete(rowKey.getBytes());
list.add(del);
table.delete(list);
table.close();
}
更新操作
//Hbase更新操作
public void updateData(String tableName, String rowKey, String column, String value) throws IOException {
HTable table = new HTable(conf, tableName);
Put p = new Put(Bytes.toBytes(rowKey));
p.add(Bytes.toBytes("detail"), Bytes.toBytes(column), Bytes.toBytes(value));
table.put(p);
table.close();
}
6.性能优化
初步设计方案在测试中发现Got ping response for sessionid
,远程主机强制关闭一个连接以及您本机中的软件关掉一个连接,这样的错误。百思不得其解,后来小伙伴看了下之前的代码,找到了错误的源头:
①每提交一次,就会执行一次Controller方法,而连接Hbase的操作放在这个方法中,所以每次都会连接一次。
②而Hbase在通过java进行交互的时候,需要知道待操作的数据的表名,通过
HTable table = new HTable(conf,tableName)
这个可以通过放在一个map中,来避免每次的new的耗时;
具体操作为,定义一个Map:Map
,在构造方法中初始化这个Map,执行到与Hbase交互时,首先判断tableMap.get(tableName)
是否可以取到相应的HTable初始化方法,可以即直接从Map中get到这个初始化,不可以说明是第一次,需将tableName和初始化方式添加给这个Map。具体代码如下:
if(tableMap.get(tableName)==null)
{
tableMap.put(tableName,
new HTable(util.getConf,tableName));
}
HTable table = tableMap.get(tableName);
③同时之前有一个误区,就是在操作Hbase的时候,Hbase不能批量进行插入,以为每次在put的时候,只能一个value,所以将put操作放到了循环中,改良后的操作方式为将每次提交的数据中的value一次性添加到put中,一次性提交这个put。
做到以上三点,基本上就没出现过上述错误,并且一万条数据耗时100秒,而生产场景的巅峰值是一秒60几条,绰绰有余。
7.常见问题
- eclipse (kepler) 创建 maven 项目 添加src/main/java出问题
- maven 加入json-lib.jar 报错 Missing artifact net.sf.json-lib:json-lib:jar:2.4:compile
- 解决maven引用jdk中的tools.jar报Missing artifact的问题
- The processing instruction target matching "[xX][mM][lL]" is not allowed怎么办?
- eclipse导出jar包export-->runnable jar file的launch configuration里的内容不更新解决
- 经过web.xml加载spring容器时遇到java.lang.ClassNotFoundException: org.springframework.web
(如若不行试着删除WebApp lib目录下的com.google.jar包)*