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

  • Post author:
  • Post category:java
















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


,再调用


Hbase





Java


接口


(


亦即


C->jni->Java)


,但这种架构方式,会导致性能下降,该如何解决这个议题呢


?


Answer(


高老师


)


回答:


这个议题可以将


Command flow





Data  flow


分开来。并且离清你的


Data Source





C





(


可能是先已经从


Hbase


查询出来,放在


C


层了


)


或是还在


Java


层的


Hbase


里。如果


Data Source


是在


Hbase


里,其


thrif


接口就是


Data Source


接口。因此,


Data Source


接口都在


C


层,而你的


Client (Data destination)


是在


C


层。于是:


  • Data flow





    C->C


    ,不要经由


    Java


    层,效率就极高。


  • Command flow


    可以经过


    Java


    层,有助于控制点放在


    Java


    层。


  • Command flow





    C->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





当今的


.NET





iOS





Android


平台都是这种架构,而


App


就是一种插件,应用层也是插件层。



Q&A#7




Question




Framework-based


平台如何保护底层


(


引擎


)


模块的变动自由度呢


?


Answer(


高老师


)


回答:




兹以


Database


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


102026413.png





这会


降低引擎的变动自由度。兹


优化以下上述的架构:加上一个


EIT


造形,如下图所述:








102246463.png









EIT


造形直接落实为类别


(


代码


)


,如下圗:



102218393.png





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


  • 此架构的控制点在哪里


    ? myDbHelper


    类别是谁开发的呢


    ?





  • E


    IT


    造形与


    Factory


    模式有何差异呢


    ?


  • EIT


    造形如何保护


    DB


    引擎的变动自由度呢


    ?


  • SQLite


    引擎可以





    没钱就改版,改版就有钱








    ?







Q&A#8





Question




如何规划


(


设计


)


云平台的


<


业务规则


(BR)


引擎


>


挿件架构呢


?


Answer(


高老师


)


回答:




首先替引擎设计一个


EIT


造形,并将成长为框架,如下途所述:


102513100.png



其中,插件包括


3


种:


App(


用户


)


插件、业务


(


业主


)


插件和平台插件。如下图:



102556985.png






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



102700178.png








看似复杂的架构,却只是


3





EIT


造形的巧妙组合而已。






Q&A#9





Question




如何采


敏捷


(Agile)





RUP


的跌代过程来建置云平台呢


?


Answer(


高老师


)


回答:




这两种方法都是跌代


(Iterative)


的模式


,也都是渐增


(Incremental)


的模式。首先,需求分析可以衔接传统的


<


双插式分析法


>


,如下图:



103335704.png



接着,定订出优先的


User Story


;并进一步以


System Use Case


表达出来。


依循


I&I





Use 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


:为什么


Java





C


函数不能直接互相调用呢


?



答:


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_1





env_2


各指向那一个


JNIEnv


对象呢


?


如果有两条线程


(





th-x





th-y)


都执行


f1()


函数时,又如何呢


?



答:此时


env_1





env_2


都指向同一个


JNIEnv


对象。



如下图:







180414796.png


如果有两条线程

(



th-x



th-y)

都执行

f1()

函数时,

此时


env_1


指向不同的


JNIEnv


对象。

如下图:






180507887.png



如果由不同的线程分别去执行


f1()





f2()


,此时


env_1





env_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



版权声明:本文为weixin_34203426原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。