<Java/Hbase + C>多层框架(大数据)云平台的架构设计_答问集

本文探讨了&lt;Java/Hbase+C&gt;多层框架的大数据云平台架构设计,解答了关于性能优化、插件架构设计等问题,并详细介绍了Java与C整合技术——JNI的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

wKioL1MFd2yjSC3SAAEfgKFAUB8610.jpg

ee                                                                        ee

欢迎访问 ==>高老师的博客网页

高焕堂:MISOO(大数据.大思考)联盟.台北中心和东京(日本)分社.总教练


EE                                                                        EE

<Java/Hbase + C>多层框架(大数据)云平台的架构设计_答问集


Part-One:設計思維

$$                                  $$  


Q&A#1

Question

在建置大数据平台时采用Hbase。这H base是以Java开发的,其提供了Java基础接口,在C层则使用 thrift机制。如果咱们的C层模块想存取Hbase时,使用的技术是:C调用jni,再调用HbaseJava接口(亦即C->jni->Java),但这种架构方式,会导致性能下降,该如何解决这个议题呢?

Answer(高老师)回答:

这个议题可以将Command flowData  flow分开来。并且离清你的Data SourceC(可能是先已经从Hbase查询出来,放在C层了)或是还在Java层的Hbase里。如果Data Source是在Hbase里,其thrif接口就是Data Source接口。因此,Data Source接口都在C层,而你的Client (Data destination)是在C层。于是:

  • Data flowC->C,不要经由Java层,效率就极高。

  • Command flow可以经过Java层,有助于控制点放在Java层。

  • Command flowC->JNI->Java接口,要求Java模块把HBase端的C接口传递给Client

  • Data flow: Client调用HBase端的C接口(若跨进程,可透过IBinder

),取得data


Q&A#2

Question

Command flow和Data flow兩者之間的關係是什麼? 是控制的關係嗎?

Answer(高老师)回答:

软件有两种flow一种是Command flow;另一种是data flow。例如控制camera的信息是Control flow;而传送preview视像的是data flow。可以透过command flow API去通知两端的模块,动态取动两端插件,透过动态API(Config文件提供)串接两端;静态Command API支撑动态Data API


Q&A#3

Question

C/C++平台上建立Java框架,其主要目的是什么?

Answer(高老师)回答:

Java Client端开发者自己来撰写后台的插件。于是,后台成为一朵真正的云(Cloud)了。一个C/C++平台可以搭配多个不同语言的框架。兹以Java为例,可使用JNI(Java Native Interface)。其中,C/C++平台的<业务规则BR引擎>可以搭配一个Java框架。如下图:


101355317.png

因为C/C++模块(<业务规则引擎>)可以调用Java函数,所以C/C++平台仍然拥有主控权。


Q&A#4

Question

高老师,有没有提升<Java /Hbase+C>平台架构质量的要点?

Answer(高老师)回答:

2003年,我在日本东京工作时,曾经提出<Java+C>多层平台架构的十项主要法则,并且创作LW_OOPC语言来实现实现这十项法则。

请参考:<Java+C>多层平台架构的十项法则


Q&A#5

Question

我的Android应用app怎么设计架构呢? 我希望分层的方式设计,我一直找不到好的设计方式,请高老师帮忙解惑。

Answer(高老师)回答:

我认为App不是分layer,这样会让App绑住于系统平台。我认为App应该分离出插件(Plug-in),包括()平台(OS而变)的插件、()用户(而变的)插件、买主插件等等;然后以Framework-based平台(phoneGap)包容起来,让插件能PnP


Q&A#6

Question

什么是Framework-based 平台呢?

Answer(高老师)回答:

简单的公式是:平台=框架+引擎。相对上,古典的观念里,其公式是:平台=(服务)引擎。例如:

101443287.png

上图是古典思维下的架构。在Framework-based新思维下,为了维护底层<引擎>的变动自由度,就采用新架构,如下:

101522929.png


于是,得出典型的Framework-based平台架构:

101555715.png


当今的.NETiOSAndroid平台都是这种架构,而App就是一种插件,应用层也是插件层。


Q&A#7

Question

Framework-based平台如何保护底层(引擎)模块的变动自由度呢?

Answer(高老师)回答:

兹以Database引擎来说明之。在传统的平台架构里,其结构为:

102026413.png


这会降低引擎的变动自由度。兹优化以下上述的架构:加上一个EIT造形,如下图所述:

102246463.png


EIT造形直接落实为类别(代码),如下圗:

102218393.png


我相信,基于这个优化的架构设计,你就很容易取得下列问题的答案了:

  • 此架构的控制点在哪里? myDbHelper类别是谁开发的呢?

  • EIT造形与Factory模式有何差异呢?

  • EIT造形如何保护DB引擎的变动自由度呢?

  • SQLite引擎可以没钱就改版,改版就有钱?


Q&A#8

Question

如何规划(设计)云平台的<业务规则(BR)引擎>挿件架构呢?

Answer(高老师)回答:

首先替引擎设计一个EIT造形,并将成长为框架,如下途所述:102513100.png


其中,插件包括3种:App(用户)插件、业务(业主)插件和平台插件。如下图:

102556985.png


当插件增多了,需要设计插件管理机制。如下图:102700178.png


看似复杂的架构,却只是3EIT造形的巧妙组合而已。


Q&A#9

Question

如何采敏捷(Agile)RUP的跌代过程来建置云平台呢?

Answer(高老师)回答:

这两种方法都是跌代(Iterative)的模式,也都是渐增(Incremental)的模式。首先,需求分析可以衔接传统的<双插式分析法>,如下图:

103335704.png

接着,定订出优先的User Story;并进一步以System Use Case表达出来。依循I&IUse Case-Driven途径,以 EIT造形来表示接口,如下图:

103557601.png

然后将EIT造形落实为类别和代码,如下图:

103648756.png


随着<领域概念>分析和<业务规则>分析,得到更多的业务概念、类别和规则,就以前面所述的<平台&插件>关系来组织和重构。如下图所示:

103715625.png


此架构模式,既能搭配敏捷开发,也能搭配RUP方法。


Q&A#10

Question

Framework-based云平台如何<插件接口>Client端呢?

Answer(高老师)回答:

通常后台的业务或平台插件的开发者Client开发者是不同的而且开发的时间点也不一样(插件常开发在先)。如下图:

103903681.png

那么,当Client需要调用插件时后台如何提工插件接口给Client开发者呢?即使Client端可以从文件中得知插件的接口又如何调用呢?首先后台<E&I>提供一个通用型接口内含一个通用型函数。然后,后台提供一个Proxy类别给Client。如下图:

103929696.png

基于这个架构,你应该可以知道如何提供Proxy类别的代码给Client开发者了。


=========================================================

相關文章:<Android与iOS/WP8跨平台整合设计与开发 专栏>



$$                                                                         $$  

Part-Two:Java與C整合技術-- JNI

$$                                                                         $$  

Q-1:在执行Java代码时,如果Java需要与本地代码(如以C写成的*so动态库)沟通时,VM(虚拟机)扮演甚么角色呢?

答:Java代码在VM上执行。如下图:

175233712.png

  在执行Java代码的过程中,如果Java需要与本地代码(如以C写成的*so动态库)沟通时,VM就会把*.so视为插件(Plug-in)而加载到VM里,然后让Java函数顺利地呼叫到这插件里的C函数。


Q-2:接续上一题,VM在那一个时间点,会去加载所需要的插件呢?

答:请参考下述的代码范例:

// MediaPlayer.java

public class MediaPlayer{    

  static {

      System.loadLibrary("media_jni");

  }

……..

}

当这个Java类被加载(Load)时,就会执行System.loadLibrary()函数,而加载这个media_jni.so插件。如下图:

175339136.png


Q-3:为什么JavaC函数不能直接互相调用呢?

答:Java代码执行于VM,它透过VM来调用*.so插件,并不直接调用插件里的本地add()函数。如下图:

175437820.png

    C代码执行于CPU,必须透过VM才能获得Java代码的攸关资源,例如取得Java类里的属性及函数ID等。


Q-4:本地C函数(add()函数)的第1个参数是:JNIEnv *env;如下述代码:

// com_misoo_pk01_addActivity.cpp

………

JNIEXPORT jlong JNICALL  

   Java_com_misoo_pk01_addActivity_add

               (JNIEnv *env, jobject thiz, jint x, jint y){

         // ……….      

      }

// ………

请问,这个JNIEnv类的内涵是什么? 这个env指针(Pointer)有什么用途呢?

答:在Java环境里,每一个线程(Thread)第一次进入VM去调用本地函数时,VM会替它诞生一个相对映的JNIEnv对象,记录该线程的状态。而且,该线程每次调用本地函数时,都会将其对映的JNIEnv对象指针值传递给本地函数。不同的线程,会使用不同的JNIEnv对向来与 VM通信。这样有助于化解多线程的冲突问题。如下图:

180152130.png

Q-5:有两个本地函数f1()f2(),其代码片段如下:

JNIEXPORT jlong JNICALL  

   Java_com_misoo_pk01_addActivity_f1(JNIEnv *env_1, jobject thiz){

         // ……….      

      }

JNIEXPORT jlong JNICALL  

   Java_com_misoo_pk01_addActivity_f2(JNIEnv *env_2, jobject thiz){

         // ……….      

      }

}

请问:当同一条线程去执行f1()f2()函数,此时env_1env_2各指向那一个JNIEnv对象呢?

如果有两条线程(th-xth-y)都执行f1()函数时,又如何呢?

答:此时env_1env_2都指向同一个JNIEnv对象。如下图:

180414796.png

  如果有两条线程(th-xth-y)都执行f1()函数时,此时env_1指向不同的JNIEnv对象。如下图:

180507887.png

   如果由不同的线程分别去执行f1()f2(),此时env_1env_2各指向不同的JNIEnv对象。如下图:

180642123.png

Q-6:当 UI线程经由VM而去执行本地C函数时,UI线程如何去创建一个小线程呢?

答:兹写代码范例如下:

/* com.misoo.counter.CounterNative.cpp */

#include <stdio.h>

#include <pthread.h>

#include "com_misoo_counter_CounterNative.h"

jmethodID mid;

jclass mClass;

JavaVM *jvm;

pthread_t thread;

int n, sum;

void* trRun( void* );

void JNICALL

Java_com_misoo_counter_CounterNative_nativeSetup(JNIEnv *env, jobject thiz) {

  jclass clazz = env->GetObjectClass(thiz);

  mClass = (jclass)env->NewGlobalRef(clazz);

  mid = env->GetStaticMethodID(mClass, "callback", "(I)V");

}

void JNICALL

Java_com_misoo_counter_CounterNative_nativeExec

(JNIEnv *env, jobject thiz, jint numb){

  n = numb;

  pthread_create( &thread, NULL, trRun, NULL);

}

void* trRun( void* ){

   int status;

  JNIEnv *env;    bool isAttached = false;

  status = jvm->GetEnv((void **) &env, JNI_VERSION_1_4);

  if(status < 0) {

       status = jvm->AttachCurrentThread(&env, NULL);

       if(status < 0)  return NULL;

       isAttached = true;  

    }

  sum = 0;

  for(int i = 0; i<=n; i++)  sum += i;

  env->CallStaticVoidMethod(mClass, mid, sum);

  if(isAttached) jvm->DetachCurrentThread();

  return NULL;

}

在本地C函数里所创建的小线程,VM并没有给它专属的JNIEnv对象。所以调AttachCurrentThtread()函数,向VM索取一个JNIEnv对象。取得JNIEnv对象之后,就能调用CallStaticVoidMethod()等函数,请VM协助存取Java层的资源(如调用Java层函数)

88                                                                    99


<think>我们有两个引用内容,其中引用[1]提到了配置hbase-site.xml的几个关键属性,包括hbase.rootdir、hbase.cluster.distributedhbase.zookeeper.quorum。引用[2]则提到了如果使用外置ZookeeperHadoopHA群时需要注意的事项。用户需求:在HBase配置文件中设置两个属性:1.hbase.rootdir=hdfs://cluster/hbase2.hbase.zookeeper.quorum=zk1,zk2,zk3步骤:1.定位到HBase的配置文件:通常位于$HBASE_HOME/conf/目录下,需要修改的文件是hbase-site.xml。2.编辑hbase-site.xml文件,添加或修改这两个属性。3.注意:如果使用HDFS群,且是HA模式(即hdfs://cluster中的cluster是一个服务名,对应多个NameNode),那么还需要将Hadoop的配置文件(core-site.xmlhdfs-site.xml)复制到HBase的conf目录下,否则HBase无法识别HDFS的HA配置[^2]。4.如果使用外置Zookeeper群(即不是HBase自带的Zookeeper),需要确保hbase-env.sh中设置HBASE_MANAGES_ZK为false,并且将Zookeeper的配置文件zoo.cfg复制到HBase的conf目录下[^2](但用户没有提到这个,我们只配置hbase-site.xml)。具体操作:###1.编辑hbase-site.xml使用文本编辑器(如vim)打开hbase-site.xml:```bashvim$HBASE_HOME/conf/hbase-site.xml```在`<configuration>`标签内添加或修改以下属性:```xml<configuration><!--设置HBase的根目录,指向HDFS--><property><name>hbase.rootdir</name><value>hdfs://cluster/hbase</value></property><!--设置Zookeeper的群地址--><property><name>hbase.zookeeper.quorum</name><value>zk1,zk2,zk3</value></property><!--其他配置...--></configuration>```注意:-`hdfs://cluster/hbase`中的`cluster`是HDFS服务的逻辑名称(如HadoopHA中配置的nameservice),请确保它与Hadoop群中的配置一致。-`zk1,zk2,zk3`是Zookeeper群的主机名(或IP),用逗号分隔。###2.配置HadoopHA(如果需要)如果Hadoop群是HA模式,需要将Hadoop配置文件复制到HBase的conf目录:```bashcp/path/to/hadoop/etc/hadoop/core-site.xml$HBASE_HOME/conf/cp/path/to/hadoop/etc/hadoop/hdfs-site.xml$HBASE_HOME/conf/```###3.配置hbase-env.sh(如果使用外置Zookeeper)如果使用外置Zookeeper,需要在hbase-env.sh中设置:```bashvim$HBASE_HOME/conf/hbase-env.sh```找到以下行并取消注释(或添加):```bashexportHBASE_MANAGES_ZK=false```###4.复制Zookeeper配置文件(如果使用外置Zookeeper且需要额外配置)如果Zookeeper群有自定义配置(比如zoo.cfg),可以复制到HBase的conf目录:```bashcp/path/to/zookeeper/conf/zoo.cfg$HBASE_HOME/conf/```###5.注意事项-修改配置后,需要重启HBase才能使配置生效。-确保HBase可以访问所有Zookeeper节点(网络端口通畅)。-确保HBase可以访问HDFS,并且有权限在HDFS上创建`/hbase`目录。###验证配置启动HBase后,可以通过HBaseWebUI(默认端口16010)查看HBase根目录是否指向正确的HDFS路径,以及Zookeeper的连接状态。###相关引用说明-根据引用[1]配置hbase-site.xml中的关键属性[^1]。-根据引用[2],在HA环境下需要复制Hadoop配置文件[^2]。§§相关问题§§1.如何配置HBase以使用HadoopHA群?[^2]2.HBase启动时如何验证Zookeeper连接是否正常?3.为什么需要设置`hbase.cluster.distributed`属性?它与HBase的运行模式有什么关系?[^1]</think> ### 配置HBase群属性指南 以下是配置 `hbase.rootdir` `hbase.zookeeper.quorum` 属性的详细步骤: #### 1. **编辑主配置文件** 打开 `hbase-site.xml` 进行配置: ```bash sudo vim $HBASE_HOME/conf/hbase-site.xml ``` 在 `<configuration>` 标签内添加: ```xml <configuration> <!-- 设置HDFS根目录 --> <property> <name>hbase.rootdir</name> <value>hdfs://cluster/hbase</value> </property> <!-- 配置ZooKeeper群 --> <property> <name>hbase.zookeeper.quorum</name> <value>zk1,zk2,zk3</value> </property> <!-- 启用分布式模式 --> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> </configuration> ``` #### 2. **配置环境变量(可选)** ```bash sudo vim $HBASE_HOME/conf/hbase-env.sh ``` 添加或修改: ```bash # 禁用内置ZooKeeper export HBASE_MANAGES_ZK=false ``` #### 3. **HA群额外配置** 如果HDFS是HA群: ```bash # 复制Hadoop配置文件 cp $HADOOP_HOME/etc/hadoop/core-site.xml $HBASE_HOME/conf/ cp $HADOOP_HOME/etc/hadoop/hdfs-site.xml $HBASE_HOME/conf/ ``` #### 4. **验证配置** ```bash hbase shell --config $HBASE_HOME/conf > status ``` 预期输出包含: ``` active master: ... regionservers: 3 zookeeper quorum: zk1,zk2,zk3 ``` #### 关键说明 1. **HDFS路径格式**: - `hdfs://cluster/hbase` 中 `cluster` 是HDFS命名服务ID(需与Hadoop配置一致) - 确保HBase对HDFS目录有写权限:`hdfs dfs -mkdir /hbase && hdfs dfs -chown hbase:hbase /hbase` 2. **ZooKeeper配置要求**: - 所有节点需配置 `/etc/hosts` 解析zk1/zk2/zk3 - 默认端口2181,如需修改端口: ```xml <property> <name>hbase.zookeeper.property.clientPort</name> <value>2182</value> </property> ``` 3. **配置生效**: - 修改后需重启HBase:`stop-hbase.sh && start-hbase.sh` - 检查日志:`tail -f $HBASE_HOME/logs/hbase-*.log` 4. **安全性配置**(若启用Kerberos): ```xml <property> <name>hbase.security.authentication</name> <value>kerberos</value> </property> ``` 根据引用[1],配置分布式模式时需要同时设置 `hbase.cluster.distributed=true`[^1];根据引用[2],HA群需复制Hadoop配置文件[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值