如何在Java中连接远程HBase?

41

我有一个独立的HBase服务器。 这是我的hbase-site.xml:

<configuration>
 <property>
    <name>hbase.rootdir</name>
    <value>file:///hbase_data</value>
  </property>
</configuration>

我正在尝试编写一个Java程序来操作HBase中的数据。

如果我在HBase服务器上运行该程序,它可以正常工作。但是我不知道如何配置它以进行远程访问。

  Configuration config = HBaseConfiguration.create();
   HTable table = new HTable(config, "test");
   Scan s = new Scan();

我尝试添加IP地址和端口,但未成功:

config.set("hbase.master", "146.169.35.28:60000")

有人可以告诉我怎么做吗?

谢谢!


你成功让它为你工作了吗?下面的答案对我没用,这里是堆栈跟踪 - bachr
5个回答

31

这是我们使用的一个系统的代码片段,用于创建一个HTable,我们用它来连接到HBase。

Configuration hConf = HBaseConfiguration.create(conf);
hConf.set(Constants.HBASE_CONFIGURATION_ZOOKEEPER_QUORUM, hbaseZookeeperQuorum);
hConf.setInt(Constants.HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT, hbaseZookeeperClientPort);

HTable hTable = new HTable(hConf, tableName);

希望有所帮助。

编辑:示例值:

public static final String HBASE_CONFIGURATION_ZOOKEEPER_QUORUM                     = "hbase.zookeeper.quorum";
public static final String HBASE_CONFIGURATION_ZOOKEEPER_CLIENTPORT                 = "hbase.zookeeper.property.clientPort";
...
hbaseZookeeperQuorum="PDHadoop1.corp.CompanyName.com,PDHadoop2.corp.CompanyName.com";
hbaseZookeeperClientPort=10000;
tableName="HBaseTableName";

你好,能告诉我一些示例值吗? - leon
你还需要确保你的HBase已经设置好接受来自外部计算机的连接。例如,不要在任何设置中使用“localhost”或“127.0.0.1”。检查你的默认设置,确保它们没有在你不知情的情况下使用这些值。 - David
这对我不起作用,我已经把堆栈跟踪放在这里 - bachr

13

hbase.master已被@Deprecated。客户端使用Zookeeper获取其HBase服务器的当前主机名和端口。

@Deprecated
config.set("hbase.master", "146.169.35.28:60000")

Hadoop和HBase对DNS和/etc/hosts配置非常敏感。确保您的主机名不指向127.0.0.1,否则它将仅在本地主机上启动许多服务。尽量不要在设置中使用IP地址。

我的/etc/hosts:

192.168.2.3     cloudera-vm     # Added by NetworkManager
127.0.0.1       localhost.localdomain   localhost
127.0.1.1       cloudera-vm-local localhost

/etc/hbase/hbase-site.xml应该设置distributed=false(因为您仅用于测试):

<property>
  <name>hbase.cluster.distributed</name>
  <value>false</value>
</property>

/etc/zookeeper/zoo.cfg

# the port at which the clients will connect
clientPort=2181
server.0=cloudera-vm:2888:3888

我Java进程的列表:

root@cloudera-vm:~# jps
1643 TaskTracker
1305 JobTracker
1544 SecondaryNameNode
2037 Bootstrap
9622 DataNode
10144 Jps
9468 NameNode
1948 RunJar
9746 HMaster

编辑 /etc/hosts 文件起了作用。我需要将公共主机名与公共 IP 地址关联起来,而不是回环地址。例如 192.168.2.3 cloudera-vm 而不是 127.0.0.1 cloudera-vm - X. Wo Satuk
刚刚花了4天时间尝试让HBase正常工作,结果发现一直出错的原因只是我的主机名指向了本地主机。你让我开心了! - habitats

11

简而言之,这就是我使用的东西:

    Configuration hBaseConfig =  HBaseConfiguration.create();
    hBaseConfig.setInt("timeout", 120000);
    hBaseConfig.set("hbase.master", "*" + hbaseHost + ":9000*");
    hBaseConfig.set("hbase.zookeeper.quorum",zookeeperHost);
    hBaseConfig.set("hbase.zookeeper.property.clientPort", "2181");

对于hBaseHost和zookeeperHost,我只是传递安装有zookeeper的群集计算机的IP地址。当然,您也可以将端口号参数化。我不确定这是否是确保成功连接的最佳方法,但到目前为止,它可以正常工作,没有任何问题。


1
据我所知,如果您想连接到远程HBase服务器,则普通的Java客户端无法正常工作。在其中我们只声明配置并尝试连接到远程HBase,就像之前的回答中提到的那样。
我尝试过上述方法,但从未成功过。相反,我使用Thrift API来连接远程服务器。 此链接是使用Thrift API Java客户端的最佳示例。它肯定有效。我正在使用相同的方法。但在使用之前,请仔细查看代码并删除不需要的内容。我也会提供成功运行的示例代码。
public class ThriftClient 
{

    port = 9090;
    //Connection to hbase
    TTransport transport = new TSocket(hostname, port);
    TProtocol protocol = new TBinaryProtocol(transport, true, true);
    Hbase.Client client = new Hbase.Client(protocol);

    transport.open();

    int z=Link.length();
    byte[] tablename = bytes("YOUR TABLE NAME");

    // Create the demo table with two column families, entry: and unused:
    ArrayList<ColumnDescriptor> columns = new ArrayList<ColumnDescriptor>();
    ColumnDescriptor col = null;
    col = new ColumnDescriptor();
    col.name = ByteBuffer.wrap(bytes("YOUR_COLUMN_FAMILY_NAME"));
    col.maxVersions = 10;
    columns.add(col);

    System.out.println("creating table: " + utf8(tablename));
    try 
    {
        client.createTable(ByteBuffer.wrap(tablename), columns);
    } 
    catch (AlreadyExists ae) 
    {
        System.out.println("WARN: " + ae.message);
    }

    Map<ByteBuffer, ByteBuffer> dummyAttributes = null;
    boolean writeToWal = false;
    // Test UTF-8 handling
    byte[] invalid = {(byte) 'f', (byte) 'o', (byte) 'o', (byte) '-',
        (byte) 0xfc, (byte) 0xa1, (byte) 0xa1, (byte) 0xa1, (byte) 0xa1};
    byte[] valid = {(byte) 'f', (byte) 'o', (byte) 'o', (byte) '-',
        (byte) 0xE7, (byte) 0x94, (byte) 0x9F, (byte) 0xE3, (byte) 0x83,
        (byte) 0x93, (byte) 0xE3, (byte) 0x83, (byte) 0xBC, (byte) 0xE3,
        (byte) 0x83, (byte) 0xAB};


    ArrayList<Mutation> mutations;

    // Run some operations on a bunch of rows

    NumberFormat nf = NumberFormat.getInstance();
    nf.setMinimumIntegerDigits(10);
    nf.setGroupingUsed(false);
    byte[] row=bytes("YOUR ROW NAME");

    mutations = new ArrayList<Mutation>();
    mutations.add(new Mutation(false, ByteBuffer.wrap(bytes("YOUR_COLUMN_FAMILY_NAME:YOUR_COLUMN_NAME")), ByteBuffer.wrap(bytes("YOUR_ROW_VALUE")), writeToWal));
    client.mutateRow(ByteBuffer.wrap(tablename), ByteBuffer.wrap(row), mutations, dummyAttributes);

    transport.close();

    // Helper to translate byte[]'s to UTF8 strings
private static String utf8(byte[] buf) {
    try {
        return decoder.decode(ByteBuffer.wrap(buf)).toString();
    } catch (CharacterCodingException e) {
        return "[INVALID UTF-8]";
    }
}

// Helper to translate strings to UTF8 bytes
private static byte[] bytes(String s) {
    try {
        return s.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
        return null;
    }
}
}

0
在我使用/etc/hosts文件进行大量尝试后,我最终在日志文件"hbase-bgi-master-servername.log"中找到了以下行:
"2017-11-21 19:56:32,999 INFO [RS:0;servername:45553] regionserver.HRegionServer: Serving as servername.local.lan,45553,1511290584538, RpcServer on servername.local.lan/172.0.1.2:45553, sessionid=0x15fdff039790002"
请务必确保完整的主机名(在我的情况下为"servername.local.lan")实际上在客户端和服务器端都指向服务器的IP。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接