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

ee                                                                        ee

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

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


EE                                                                        EE

多层框架(大数据)云平台的架构设计_答问集


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框架。如下图:


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

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


Q&A#4

Question

高老师,有没有提升平台架构质量的要点?

Answer(高老师)回答:

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

请参考:多层平台架构的十项法则


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(高老师)回答:

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

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

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

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


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

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


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


Q&A#7

Question

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

Answer(高老师)回答:

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

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


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

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


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

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


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

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

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

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

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


Q&A#8

Question

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

Answer(高老师)回答:

首先替引擎设计一个EIT造形,并将成长为框架,如下途所述:<Java/Hbase + C>多层框架(大数据)云平台的架构设计_答问集_第9张图片


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

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


当插件增多了,需要设计插件管理机制。如下图:<Java/Hbase + C>多层框架(大数据)云平台的架构设计_答问集_第11张图片


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


Q&A#9

Question

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

Answer(高老师)回答:

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

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

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

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

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

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


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

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


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


Q&A#10

Question

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

Answer(高老师)回答:

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

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

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

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

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


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

相關文章:



$$                                                                         $$  

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

$$                                                                         $$  

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

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

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

  在执行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插件。如下图:

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


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

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

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

    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通信。这样有助于化解多线程的冲突问题。如下图:

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

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对象。如下图:

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

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

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

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

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

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

答:兹写代码范例如下:

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

#include

#include

#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