日志

.net hbase client--终于浮出水面的轮子

 来源    2020-08-02    0  

一、开篇

1.背景

在大数据时代,HBase 数据库是个绕不开的热门话题。 由于其使用 Java 作为主要开发语言,并且依赖大量的 Java 组件(如 Hadoop、zooKeep),使得其他技术栈想要有一个对应的 hbase 客户端变得有一定难度。在 .net 的世界中,一直缺乏能够直接访问 hbase 的客户端。

2.历程

Apache Thrift 作为社区内比较有名的支持多语言的 Api 服务,可以解决跨语言访问 HBase 数据库的痛点。在以往的文章中业也介绍过 C#如何使用 thrift 访问 hbase,但在真正的生产环境中,该方式的访问效率和原生 Java 客户端比起来真着实让人心灰意冷。此外,thrift 也要求服务端和客户端版本一致。

Protocol Buffers HBase 提供基于 Protocol 的数据访问,这以一种相对高效紧凑的数据交换规则。基于此,我们能够造出属于 .net 的 hbase 客户端。

这是一个造轮子的过程,中间虽有着许多难点就不再赘述。下面直接介绍该项目的使用。

二、HBaseNet 使用

1.HBase 数据库准备

作为项目使用演示,我们就不讨论如何搭建 HBase 集群了,一切以简单便捷为前提,直接使用别人构建好的 docker 镜像就可以轻松获取 HBase 数据库的使用。

在 dockerhub 中搜索 hbase 或者命令行:docker search hbase。结果中找到dajobe/hbase,将其 pull 到本地就行。可以按照作者教程进行部署。其核心操作也就几个简单命令,现作一简单摘抄:

docker pull dajobe/hbase # 拉取镜像到本地
mkdir data # 创建名为data的目录
id=$(docker run --name=hbase-docker -h hbase-docker -d -v $PWD/data:/data dajobe/hbase) #将hbase-docker设置为主机名运行,并将docker容器id赋值给id

命令行docker inspect hbase-docker|grep IPAddress查看 hbase 主机地址:

"SecondaryIPAddresses": null,
"IPAddress": "172.17.0.2",
        "IPAddress": "172.17.0.2",

可以看到我的在 172.17.0.2 上,我们可以直接浏览器访问http://172.17.0.2:16010/,看到habse的主页说明部署成功。此外,最好将本地物理机的hosts修改以作映射,文件中添加一行172.17.0.2 hbase-docker即可。

2.HBaseNet 简单演示

演示项目创建

首先创建控制台项目dotnet new console -o HBaseNetTest,然后添加 HBaseNet 客户端 nuget dotnet add package HBaseNet --version 0.1.0-rc2-final

使用 AdminClient 创建 HBase 表

直接在主函数中写下如下代码:

static async Task Main(string[] args)
{
    // 注意在hosts中添加地址映射
    var ZkQuorum = "hbase-docker";
    var admin = await new AdminClient(ZkQuorum).Build();
    if (admin == null) return;
    var table = "products";
    var cols = new[] { new ColumnFamily("info") };//名为info的列簇
    var create = new CreateTableCall(table, cols)
    {
        SplitKeys = new[] { "8" }// 预分区
    };
    //简单判断表是否存在
    var tables = await admin.ListTableNames(new ListTableNamesCall { Regex = table });
    if (true != tables?.Any())
    {
        //使用高级客户端创建products表
        var createResult = await admin.CreateTable(create);
        Console.WriteLine($"创建表{table}的结果:{createResult}.");
    }
    else
    {
        Console.WriteLine($"表{table}已经存在");
    }
}

运行后控制台输出创建表products的结果:True.。我们再查看主页http://hbase-docker:16010/,找到Tables,可以看到 products 表已经被创建:

default	products	ENABLED	2	0	0	0	0	0	0	0	'products', {NAME => 'info', VERSIONS => '3', DATA_BLOCK_ENCODING => 'FAST_DIFF', BLOCKCACHE => 'False', METADATA => {'TTl' => '2147483647'}}

使用 StandardClient 进行数据的写入和查询

var client = await new StandardClient(ZkQuorum).Build();
if (client == null) return;
var rowKey = "123";
var values = new Dictionary<string, IDictionary<string, byte[]>>
{
    {
        "info", new Dictionary<string, byte[]>
        {
            {"key", "value".ToUtf8Bytes()}
        }
    }
};
//放入一条数据
var rs = await client.Put(new MutateCall(table, rowKey, values));
Console.WriteLine($"放入数据key:{rowKey},结果:{rs.HasProcessed}");
// 根据rowkey获取一条数据
var getResult = await client.Get(new GetCall(table, rowKey));
Console.WriteLine($"获取数据结果key:{rowKey}");
// 使用scanner进行数据扫描
var sc = new ScanCall(table, "1", "")
{
    NumberOfRows = 1000
};
using var scanner = client.Scan(sc);
var scanResults = new List<Result>();
while (scanner.CanContinueNext)
{
    var per = await scanner.Next();
    if (true != per?.Any()) continue;
    scanResults.AddRange(per);
}
Console.WriteLine($"扫描数据共返回结果:{scanResults.Count}行");

控制台输出:

放入数据key:123,结果:True
获取数据结果key:123
扫描数据共返回结果:1行

日志配置

为了方便友好,建议还是开启日志进行使用。这里就以使用Serilog为例,添加以下 nuget 包:

dotnet add package Serilog --version 2.10.0-dev-01226
dotnet add package Serilog.Sinks.Console --version 4.0.0-dev-00839
dotnet add package Microsoft.Extensions.DependencyInjection --version 5.0.0-preview.7.20364.11

在主函数最上面添加:

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .MinimumLevel.Debug()
    .WriteTo.Console(
        outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
    .CreateLogger();
HBaseConfig.Instance.ServiceProvider = new ServiceCollection()
    .AddLogging(cfg => cfg.AddSerilog(Log.Logger))
    .BuildServiceProvider();

更多细节可以参考项目里的示例代码HBaseNet.Console

三、最后

在 .neter 中使用 hbase 的人极少,多数人还是在抱怨生态不好。但想一想自己能够做什么,付诸行动总是比无谓的抱怨要好很多的。HBaseNet是一个刚开始的项目,捂了(肝了)几个月还是把它做出来了。如果对它感兴趣,欢迎加入我们或者提出宝贵的修改意见。当然,我最终的愿望是希望它对您有用。开源不易,非常欢迎到项目主页进行 star 鼓励。

感谢。

相关文章
Hbase错误. org.apache.hadoop.hbase.client.RetriesExhaustedException:尝试次数= 10后失败,异常
问答我正在使用Hbase,当我查询Hbase时,我开始遇到一个难看的错误. 问题是当我尝试与Hbase建立连接时出现此错误.唯一的问题是我使用线程,,,但实际上并不是太多. Caused by: org. ...
1
hbase.client.keyvalue.maxsize的默认值
日志hbase的列族的最大值是在hbase配置里的hbase.client.keyvalue.maxsize,默认大小为10M,即 10485760 . http://eclecl1314-163-com ...
1
HBase Client JAVA API
日志旧 的 HBase 接口逻辑与传统 JDBC 方式很不相同,新的接口与传统 JDBC 的逻辑更加相像,具有更加清晰的 Connection 管理方式. 同时,在旧的接口中,客户端何时将 Put 写到服 ...
Spark操作HBase报:org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException异常解决方案
日志一.异常信息 19/03/21 15:01:52 WARN scheduler.TaskSetManager: Lost task 4.0 in stage 21.0 (TID 14640, hnte ...
HBase Client API使用(二)---查询及过滤器
日志相关知识 创建表插入数据删除等见:https://www.cnblogs.com/wishyouhappy/p/3735077.html HBase API简介见:https://www.cnblog ...
1
Java 向Hbase表插入数据异常org.apache.hadoop.hbase.client.HTablePool$PooledHTable cannot be cast to org.apache.client.HTable
日志出错代码如下:      //1.create HTablePool HTablePool hp=new HTablePool(con, 1000); //2.get HTable from HTab ...
3
异常 org.apache.hadoop.hbase.client.RetriesExhaustedException: Failed after attempts=36, exceptions:
日志1 Phoenix远程无法连接但是本地可以连接,详细异常 SLF4J: Class path contains multiple SLF4J bindings. SLF4J: Found bindin ...
与REST / Thrift相比,为何HBase Java Client速度较慢
问答我正在HBase Java客户端/ Thrift / REST接口上运行一些性能测试. 我有一个名为"航空公司"的表,有500K行. 我通过4个不同的Java程序从表中获取所有50 ...
1
hbase源码系列(三)Client如何找到正确的Region Server
日志客户端在进行put.delete.get等操作的时候,它都需要数据到底存在哪个Region Server上面,这个定位的操作是通过HConnection.locateRegion方法来完成的. loc ...
1
073 HBASE的读写以及client API
日志一:读写思想 1.系统表 hbase:namespace 存储hbase中所有的namespace的信息 hbase:meta rowkey:hbase中所有表的region的名称 column:re ...
1
client 如何找到正确的RegionServer(HBase -ROOT-和.META.表)
日志在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,删除,查询数据都需要先找到相应的RegionServer.什么叫相应的RegionServer?就是管理你要操 ...
使用Nest Client在Elasticsearch中加载完成字段
问答我想使用Nest将完成建议字段填充到索引中.阅读本ElasticSearch blog post about implementing a completion field后,我发现您可以拥有以下属性 ...
1
python – pip / setup.py:依赖关系解析不使用可用的轮子
问答在我的Python包中,我在setup.py中声明了一个依赖项,如下所示: setup(name="xxxx", install_requires=["pycryptod ...
1
java – HBase PrivilegedExceptionAction runAs thread?
问答我有用于获取的HBase代码(虽然我没有使用Kerberos,但我打算稍后再使用它,所以我想确保在连接和执行Put或Get时正确处理用户凭据). final ByteArrayOutputStream ...
2
javascript – 使用mocha和typescript测试Paho MQTT Client时,“窗口未定义”
问答我用谷歌搜索了几天但是找不到任何关于如何测试Paho MQTT Client的东西.我以一种天真的方式尝试了它,就像那样: import { suite, test, slow, timeout, s ...
1
python – 导入错误:找不到paho.mqtt.client
问答我正在创建一个包含python和php的docker.我正在编写一个python脚本来连接到驻留在另一个docker中的MQTT代理. 在我的dockerfile中,我确保使用以下命令安装paho客户 ...
1
用于Web应用程序的Client Java vs(Adobe)Flash,可供选择的内容和时间
问答几年前,客户端Java不适合用于Web开发,因为很多Web用户没有安装Java. (我不记得确切的数字,超过10%). 现在我看到一个大型网站的Google Analytics统计数据,它告诉我们&g ...
1
java – HBase多表扫描作业
问答我正在看下面的场景.我每天都会发送一个数据文件.我将其添加到名为file-yyyyMMdd格式的HBase中.所以在一段时间内我有很多数据库,例如 tempdb-20121220 tempdb-201 ...
1
javascript – 在Google Native Client上运行编译的文件
问答如何使用Google Native Client(PNaCl)直接运行编译文件?它试图检查他们的documentation.它说 – Native Client is a sandbox for ru ...
1
在Java中为自定义聊天室创建Server类和Client类
问答我的计划说明 我使用Java创建了一个聊天室服务器,它包含3个类,一个服务器类,一个用户类和一个聊天室类.我还创建了一个与服务器交互的客户端类.每次客户端连接到服务器时,服务器都会创建一个用户对象.每 ...
1