精华内容
下载资源
问答
  • 它是对软件系统系统组织,是对构成系统构件的接口,行为模式,协作关系等体系问题决策总和。它不仅涉及到结构与行为,而且还涉及到系统使用,功能,性能,适应性,重用性,可理解性,经济性技术约束权衡...
    软件架构,也称为软件体系结构。简单地说,软件架构就是一个蓝图,是一种设计方案,将客户的不同需求抽象成为抽象组件,并且能够描述这些抽象组件之间的通信和调用。它是对软件系统的系统组织,是对构成系统的构件的接口,行为模式,协作关系等体系问题的决策总和。它不仅涉及到结构与行为,而且还涉及到系统的使用,功能,性能,适应性,重用性,可理解性,经济性和技术约束的权衡和美学考虑。
    使用方法:软件架构会分析工程中的问题,针对问题设计解决方案,针对解决方案分析应具有的功能,针对功能设计软件系统的层次和模块及层次模块之间的逻辑交互关系,确定各个功能如何由这些逻辑实现。工程开发者,可以根据软件架构中分析出来的层次和模块进行软件的编写。


    软件框架是项目软件开发过程中提取特定领域软件的共性部分形成的体系结构,不同领域的软件项目有着不同的框架类型。框架不是现成可用的应用系统,而是一个半成品,是一个提供了诸多服务,供开发人员进行二次开发,实现具体功能的应用系统。特别强调,框架是一个可供二次开发的程序实体。
    框架与架构关系 首先说框架不是架构,框架比架构更具体,更偏重于技术,而架构偏重于设计。还有一个关系就是架构可以通过多种框架来实现。
    另外,生活中说的“框架”跟软件术语中“框架”的意思不同,要注意区别。
    使用方法:特定领域软件有一些共性部分形成的软件架构,将这个共性的软件架构开发出来,形成一个可供二次开发的程序实体,这个程序实体就是软件框架。 可供二次开发。


    设计模式强调的是一个设计问题的解决方法,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。
    框架与设计模式关系 设计模式研究的是针对单一问题的设计思路和解决方法,一个模式可应用于不同的框架和被不同的程序语言所实现;而框架则是一个应用的体系结构,是一种或多种设计模式和代码的混合体。虽然它们有所不同,但却共同致力于使人们的设计可以被重用,在思想上存在着统一性的特点,因而设计模式的思想可以在框架设计中进行应用。
    架构与设计模式关系 两者的关系也是很好区分的,设计模式主要是针对单一问题的解决方法,范畴比较小,而架构是高层次的针对体系结构的一种设计思路,范畴比较大。可以这么说,一个架构中可能会出现多个设计模式来解决多个架构中的问题。
    使用方法:针对特定问题提供解决方案,以供问题解决者参考。


    模块,module,模块是一个通用概念,可能从功能或其他目的来区分。模块可以是子系统子领域,主要取决于上下文环境的用法。通常我们会说程序模块,功能模块,这实际上是在按照不同的标准对模块的内容和范围的不同定义。
    通常我们说的程序模块,是指的一段能够实现某个有价值目标的的成员代码段,这样的东西,我们还有另一个称呼:例程,而例程有两种,即函数和过程,它们都能实现一个有价值的目标供其它的模块使用。
    而功能模块的说法一般在分析和设计阶段出现得比较频繁,通常我们用一个功能模块来说明一个功能所包含的系统行为,当我们觉得分析的颗粒度可能更大一些的时候我们可以用一个功能模块来表示一组功能的集合,这似乎让我们觉得,模块这个词的概念和“子系统”这个词的概念有些模糊,是的,事实上,有些大的模块会慢慢的让我们觉得称呼他们子系统更合适,或者一个子系统,我们会慢慢发现你还包含着一些模块。但是无论怎样,定义模块的原则应该是:高内聚和低耦合。
    使用方法:就是一个描述全局中问题的概念,至于全局是什么,这个随便,比如一个人,可以看成各种功能系统,那么模块就是各种呼吸系统、消化系统等;可以看成社会关系,模块就有劳动能力、生产关系等,全在于怎么看了。


    组件,Component,首先说,组件已经不是一个抽线的概念了,是封装了一个或多个实体程序模块的实体。
    组件这个词通常是现在描述产品的时候出现,一个大的产品会有很多小的部分组成,而小的部分除了是一个大的组件的部分以外,自己可能还包含更小的组件,所以组件是递归的,那么组件到底是什么呢?最常见的组件就是我们已经写好的程序代码,任何一小段代码都可以是一个组件,它可以和其它代码段连接起来组成更大的一段程序代码,一个更大的组件,然后可能是一个函数,或者一个类程序单元,或者数个类单元文件的集成,当不同的组件的组装形成更大的组件时候,我们实际就是在做我们通常提到的一件事情:集成,软件中有很多集成工作要做,每日集成,重要版本集成等等,集成是什么呢?软件中,就是链编调试。这样一来,我们知道集成是需要对被集成的组件有规模要求的,换句话说,至少是一个单元文件,所以通常说到的组件就可以直观的理解为单元文件,或者可以组成软件的其他文件,以及编译后的文件。
    组件是面向对象里面的一个重[chóng]用的概念,也称为构件,组件非常类似机械中构件概念,现在机械都是走向构件生成,通过不同构件组装成一个机械成品,软件目前也是这样的一个生成方式。
    维基百科上说,组件之间通过接口进行交互,这个挺起来有些象插件,现实中也是这样,比如一个dll文件,可以说是插件,也可以说是组件。插件是是组件的一个子类,就是将组件中具有某些特点的组件归为插件,这些特点是:益于与系统分离,接口明晰,可以替换的程序模块。
    组件强调的是封装,利用接口进行交互。因为封装有不同层次的封装,对应不同层次的接口,(比如将一个人封装成一个组件,比如国家主席,多个人封装成一个组合,比如中央的常委们),所以组件所表述的范围和层次也是多种多样的,在谈论组件的时候一定要分辨清楚谈论的层次和范围。层次是相对的。你说地球是整个世界,但是将地球放到银河系中,地球就显得渺小了;你说物质世界是整个世界,但是人类的精神世界也是无比的浩瀚;你说物质世界和精神世界合起来是整个世界,但是历史又是那么的神秘和真实;你说物质世界、精神世界、历史时空是整个世界,但是科学家又说人类可以探察的宇宙物质仅占全部宇宙的百分之四。
    使用方法:就是一个描述系统中实体单元的概念。
    根据对组件和模块的分析,插件属于组件,而且还是一个程序模块,也是一个功能模块。插件是一种电脑程序,通过和应用程序的互动,来替应用程式增加一些特定的功能。 插件必须依赖于应用程序才能发挥自身功能,仅靠插件是无法正常运行的。
    使用方法:满足一定接口规范的具有一定功能的程序模块。开发者可以在自己软件系统中设计相应的接口以匹配某个插件,也可以设计一定的接口规范,来让别人开发插件。插件和程序之间通过接口进行交互。


    控件,可视化的组件。


    中间件,是提供系统软件和应用软件之间连接的软件,以便于软件各部件之间的沟通。



    展开全文
  • 点击上方“高性能服务架构”,选择加"星标"置顶重磅干货,第一时间送达 这些年我参与主导过多款音视频 SDK 设计开发,也服务过大大小小几十家 toB 客户,其中,有一条深深感悟:一个 PaaS 技术中间件产品,...

    点击上方“高性能服务架构”,选择加"星标"置顶

    重磅干货,第一时间送达 45bab4eee368ffa6d6f693628c9541e6.png

          这些年我参与和主导过多款音视频 SDK 的设计和开发,也服务过大大小小几十家 toB 客户,其中,有一条深深的感悟:

    一个 PaaS 技术中间件产品,无论它的服务端 & 内核设计和实现的多么牛逼多么漂亮,最终交付给客户开发者的 SDK 才是最最关键的要素和门面,它设计得好,即使背后有不足也能有一定程度上的弥补;它设计的烂,就几乎废弃掉了底层所有的努力,还会平添无数的无效加班和问题排障的投入。

    本文关注一款优秀的 SDK 应该如何设计接口规格,以实现如下几个目标: 

    1. 简洁明了,边界清晰,接口正交(不存在 2 个接口相互冲突),使用者不容易踩坑

    2. 每一个 API 的行为确定,调用错误或者运行时异常的反馈及时准确

    3. 面向高级客户:配置丰富,回调丰富,业务扩展性和灵活性好

    这里致敬 《Effective C++》的行文模式,以条款的形式来描述和示例我的个人思考和总结(以最近深度参与的 RTC SDK 接口设计为例子)。

    条款 1 :参数配置提供独立的 profile 类,不要每个参数都提供一个 set 方法

    // good case// 记得给出合理的默认值class AudioProfile 
    {
    int samplerate{44100};
    int channels{1};
    };

    // 记得给出合理的默认值class VideoProfile
    {
    int maxEncodeWidth{1280};
    int maxEncodeHeight{720};
    int maxEncodeFps{15};
    };

    // 可以很好地进行扩展,比如 SystemProfile,ScreenProfile...class EngineProfile
    {
    AudioProfile audio;
    VideoProfile video;
    };

    class RtcEngine
    {
    public:
    static RtcEngine* CreateRtcEngine(const EngineProfile& profile) = 0;
    };

    // bad case// 1. 核心接口类 RtcEngine 的函数数量爆炸// 2. 无法约束业务方调用 API 的时间(可能在加入房间后或者某个不合适的时间去配置参数)// 3. 如果某个配置期望支持动态更新怎么办 ?通常配置是不建议频繁动态更新的(会影响 SDK 内部行为),// 如有必须,请显式在 engine 提供 updateXXXX or switchXXX 接口class RtcEngine
    {
    public:
    static RtcEngine* CreateRtcEngine() = 0;

    virtual void setAudioSampelerate(int samplerate) = 0;
    virtual void setAudioChannels(int channels) = 0;
    virtual void setVideoMaxEncodeResolution(int width, int height) = 0;
    virtual void setVideoMaxEncodeFps(int fps) = 0;
    };

    条款 2 :非运行时的状态 & 信息的查询和配置接口提供静态方法

    // good caseclass RtcEngine 
    {
    public:
    static int GetSdkVersion();
    static void SetLogLevel(int loglevel);
    };

    条款 3 :关键的异步方法附带上闭包回调告知结果

    // good casetypedef std::function<void(int code, string message)> Callback;

    class RtcEngine
    {
    public:
    // 客户可及时在 callback 中处理事件,比如:改变 UI 状态|提示错误|再次重试 virtual void Publish(Callback const& callback = nullptr) = 0;
    virtual void Subscribe(Callback const& callback = nullptr) = 0;
    };

    // bad caseclass RtcEngine
    {
    public:
    class Listener
    {
    // 需要根据 code 来详细判断错误事件,且不一定能对得上哪一次 API 调用产生的错误 // 错误种类繁多,且跳出原来的逻辑,很多业务方会忽略在这里处理一些关键错误 virtual void OnError(int code, string message) = 0;
    };

    void SetListener(Listener * listener)
    {
    _listener = listener;
    }

    virtual void Publish() = 0;
    virtual void Subscribe() = 0;

    private:
    Listener * _listener;
    };

    条款 4 :所有接口尽量保证 “正交” 关系(不存在 2 个接口相互冲突)

    // bad case// EnalbeAudio 与其他 API 接口并不 “正交”,组合起来容易用错// MuteLocalAudioStream(true) & MuteAllRemoteAudioStreams(true) 依赖了使用者先调用 EnalbeLocalAudio(true)class RtcEngine 
    {
    public:
    // EnalbeLocalAudio + MuteLocalAudioStream + MuteRemoteAudioStream virtual void EnalbeAudio(bool enable) = 0;
    // 打开本地的音频设备(麦克风 & 扬声器) virtual void EnalbeLocalAudio(bool enable) = 0;
    // 发布/取消发布本地音频流 virtual void MuteLocalAudioStream(bool mute) = 0;
    // 订阅/取消订阅远端音频流 virtual void MuteAllRemoteAudioStreams(bool mute) = 0;
    };

    条款 5 :考虑扩展性,可抽象的对象尽量用结构体代替原子类型

    // good caseclass RtcUser
    {
    string userId;
    string metadata;
    };

    class RtcEngineEventListenr
    {
    public:
    // 未来可以很容易扩展 User 的信息和属性 virtual void OnUserJoined(const RtcUser& user) = 0;
    };

    // bad caseclass RtcEngineEventListenr
    {
    public:
    // 一旦接口提供出去后,未来关于 User 对象的一些扩展信息和属性无法添加 virtual void OnUserJoined(string userId, string metadata) = 0;
    };

    条款 6 :不可恢复的退出事件使用明确的 OnExit 且给出原因

    客户在面对 SDK 提供的 OnError 回调事件的时候,由于错误种类特别多,他们往往不知道该如何应对和处理,建议有明确的文档告知处理方案。另外,当 SDK 内部发生了必须销毁对象退出页面的事件时,建议给出独立的 callback 函数让客户专门处理。

    enum ExitReason {
    EXIT_REASON_FATAL_ERROR, // 未知的关键异常 EXIT_REASON_RECONNECT_FAILED, // 断线后自动重连达到次数&时间上限 EXIT_REASON_ROOM_CLOSED, // 房间被关闭了 EXIT_REASON_KICK_OUT, // 被踢出房间了};

    class RtcEngineEventListenr
    {
    public:
    // 一些警告消息,不碍事,接着用 virtual void OnWarning(int code, const string &message) = 0;
    // 发生了必须销毁 SDK 对象的事件,请关闭页面 virtual void OnExit(ExitReason reason, const string &message) = 0;
    };

    条款 7 :PaaS 产品的 SDK 不要包含业务逻辑和信息

    // bad caseenum ClientRole {
    CLIENT_ROLE_BROADCASTER, // 主播,可以推流也可以拉流 CLIENT_ROLE_AUDIENCE // 观众,不能推流仅可以拉流};

    class RtcEngine
    {
    public:
    // 需要明确的文档介绍不同的 role 所对应的角色,以及 role 切换产生的行为 // 该 API 与其他的 API 不是 “正交” 的,比如:Publish virtual void SetClientRole(ClientRole& role) = 0;
    };

    // good case// 建议在 examples 或者最佳实践中,封装多个 SDK 的原子接口,以达成上述 API 所起到的作用class RoleManager
    {
    public:
    // 通过这种方式,客户可以显式地感知到这个 API 背后的一系列的行为动作 void SetClientRole(ClientRole& role)
    {
    // _engine->xxxxx1(); // _engine->xxxxx2(); // _engine->xxxxx3(); }

    private:
    RtcEngine * _engine;
    };

    条款 8 :请提供所有必要的状态查询和事件回调,别让使用方 cache 状态

    // good caseclass RtcUser
    {
    string userId;
    string metadata;
    bool audio{false}; // 是否打开并且发布了音频流 bool video{false}; // 是否打开并且发布了视频流 bool screen{false}; // 是否打开并且发布了屏幕流};

    class RtcEngine
    {
    public:
    // 由 SDK 内部来保持用户状态(最准确实时),并提供明确的查询 API // 而不是让客户在自己的代码中 cache 状态(很容易出现两边状态不一致的问题) virtual list<RtcUser> GetUsers() = 0;
    virtual RtcUser GetUsers(const string& userId) = 0;
    };

    条款 9 :尽可能为参数配置提供枚举能力,并且返回 bool 告知配置结果

    class VideoProfile 
    {
    public:
    // 提供能力的枚举和配置结果,从而防止客户以为的配置跟实际的情况不一致 bool IsHwEncodeSupported();
    bool SetHwEncodeEnabled(bool enabled);

    // 提供能力的枚举和配置结果,从而防止客户以为的配置跟实际的情况不一致 int GetSupportedMaxEncodeWidth();
    int GetSupportedMaxEncodeHeight();
    bool SetMaxEncodeResolution(int width, int height);
    };

    条款 10 :接口文件的位置和命名风格保持一定的规则和关系

    // good case// 某个代码 repo 的目录结构(当然,仅 Android 的包客户可感知,C++ 的库外部无法感知目录结构)// 建议所有的对外的 interface 头文件都在根目录下,而实现文件隐藏在内部文件夹中// 合理的头文件位置关系,能够帮助开发者自己 & 客户准确地感知哪些是接口文件,哪些是内部文件// 所有的对外的头文件,不允许 include 内部的文件,否则存在头文件污染问题// 所有的接口 Class 命名都以统一的风格开头,比如 RtcXXXX,回调都叫 XXXCallback 等等src
    - base
    - audio
    - video
    - utils
    - metrics
    - rtc_types.h
    - rtc_engine.h
    - rtc_engine_event_listener.h

    小结

    关于 SDK 的接口设计经验就介绍到这里了,每个人都会有自己的风格和喜好,这里仅代表我个人的一些观点和看法,欢迎留言讨论或者来信交流,或者关注我的微信公众号 获取后续更多的文章和资讯~~

    85e6fa97f2844ab0ac741996c8100968.png

    ▲长按加作者微信

    9863606ed929c54e7791f2f661cd39fe.png

    ▲长按关注【高性能服务架构】公众号

          整理不易,请给作者点亮bb1f08d18a3f1604b61007dc6559fd89.gif

    展开全文
  • jdbc与hibernate优缺点比较 浏览:3095 | 更新:2013-10-23 17:03 ... 一 Hibernate是JDBC轻量级对象封装...Hibernate可以用在任何JDBC可以使用场合,例如Java应用程序数据库访问代码,DAO接口 

    jdbc与hibernate的优缺点比较

    • 浏览:3095
    • |
    • 更新:2013-10-23 17:03

      一 Hibernate是JDBC的轻量级的对象封装,它是一个独立的对象持久层框架,和App 
    Server,和EJB没有什么必然的联系。Hibernate可以用在任何JDBC可以使用的场合,例如Java应用程序的数据库访问代码,DAO接口 
    的实现类,甚至可以是BMP里面的访问数据库的代码。从这个意义上来说,Hibernate和EB不是一个范畴的东西,也不存在非此即彼的关系。

      二、Hibernate是一个和JDBC密切关联的框架,所以Hibernate的兼容性和JDBC驱动,和数据库都有一定的关系,但是和使用它的Java程序,和App 
    Server没有任何关系,也不存在兼容性问题。

      三、Hibernate不能用来直接和Entity 
    Bean做对比,只有放在整个J2EE项目的框架中才能比较。并且即使是放在软件整体框架中来看,Hibernate也是做为JDBC的替代者出现的,而 
    不是Entity Bean的替代者出现的,让我再列一次我已经列n次的框架结构:

      传统的架构:

      1) Session Bean <-> Entity Bean <-> DB

      为了解决性能障碍的替代架构:

      2) Session Bean <-> DAO <-> JDBC <-> DB

      使用Hibernate来提高上面架构的开发效率的架构:

      3) Session Bean <-> DAO <-> Hibernate <-> DB

      就上面3个架构来分析:

      1、内存消耗:采用JDBC的架构2无疑是最省内存的,Hibernate的架构3次之,EB的架构1最差。

      2、运行效率: 
    如果JDBC的代码写的非常优化,那么JDBC架构运行效率最高,但是实际项目中,这一点几乎做不到,这需要程序员非常精通JDBC,运用Batch语 
    句,调整PreapredStatement的Batch Size和Fetch 
    Size等参数,以及在必要的情况下采用结果集cache等等。而一般情况下程序员是做不到这一点的。因此Hibernate架构表现出最快的运行效率。 
    EB的架构效率会差的很远。

      3、开发效率:在有JBuilder的支持下以及简单的项目,EB架构开发效率最高,JDBC次之,Hibernate最差。但是在大的项目,特别是持久层关系映射很复杂的情况下,Hibernate效率高的惊人,JDBC次之,而EB架构很可能会失败。

      4、分布式,安全检查,集群,负载均衡的支持 由于有SB做为Facade,3个架构没有区别。

      四、EB和Hibernate学习难度在哪里?

      EB的难度在哪里?不在复杂的XML配置文件上,而在于EB运用稍微不慎,就有严重的性能障碍。所以难在你需要学习很多EJB设计模式来避开性能问题,需要学习App 
    Server和EB的配置来优化EB的运行效率。做EB的开发工作,程序员的大部分精力都被放到了EB的性能问题上了,反而没有更多的精力关注本身就主要投入精力去考虑的对象持久层的设计上来。

      Hibernate难在哪里?不在Hibernate本身的复杂,实际上Hibernate非常的简单,难在Hibernate太灵活了。 
    当你用EB来实现持久层的时候,你会发现EB实在是太笨拙了,笨拙到你根本没有什么可以选择的余地,所以你根本就不用花费精力去设计方案,去平衡方案的好 
    坏,去费脑筋考虑选择哪个方案,因为只有唯一的方案摆在你面前,你只能这么做,没得选择。Hibernate相反,它太灵活了,相同的问题,你至少可以设 
    计出十几种方案来解决,所以特别的犯难,究竟用这个,还是用那个呢?这些方案之间到底有什么区别呢?他们的运行原理有什么不同?运行效率哪个比较好?光是 
    主键生成,就有七八种方案供你选择,你为难不为难?集合属性可以用Set,可以用List,还可以用Bag,到底哪个效率高,你为难不为难?查询可以用 
    iterator,可以用list,哪个好,有什么区别?你为难不为难?复合主键你可以直接在hbm里面配置,也可以自定义CustomerType,哪 
    种比较好些?你为难不为难?对于一个表,你可以选择单一映射一个对象,也可以映射成父子对象,还可以映射成两个1:1的对象,在什么情况下用哪种方案比较 
    好,你为难不为难? 
    这个列表可以一直开列下去,直到你不想再看下去为止。当你面前摆着无数的眼花缭乱的方案的时候,你会觉得幸福呢?还是悲哀呢?如果你是一个负责的程序员, 
    那么你一定会仔细研究每种方案的区别,每种方案的效率,每种方案的适用场合,你会觉得你已经陷入进去拔不出来了。如果是用EB,你第一秒种就已经做出了决 
    定,根本没得选择,比如说集合属性,你只能用Collection,如果是Hibernate,你会在Bag,List和Set之间来回犹豫不决,甚至搞 
    不清楚的话,程序都没有办法写。

      补充:

      JDBC与Hibernate在性能上相比,JDBC灵活性有优势。而Hibernate在易学性,易用性上有些优势。当用到很多复杂的多表联查和复杂的数据库操作时,JDBC有优势。

      相同点:

      ◆两者都是JAVA的数据库操作中间件。

      ◆两者对于数据库进行直接操作的对象都不是线程安全的,都需要及时关闭。

      ◆两者都可以对数据库的更新操作进行显式的事务处理。

      不同点:

      ◆使用的SQL语言不同:JDBC使用的是基于关系型数据库的标准SQL语言,Hibernate使用的是HQL(Hibernate query 
    language)语言

      ◆操作的对象不同:JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行,Hibernate操作的是持久化对象,由底层持久化对象的数据更新到数据库中。

      ◆数据状态不同:JDBC操作的数据是“瞬时”的,变量的值无法与数据库中的值保持一致,而Hibernate操作的数据是可持久的,即持久化对象的数据属性的值是可以跟数据库中的值保持一致的。

      JDBC与Hibernate读取性能

      1、JDBC仍然是最快的访问方式,不论是Create还是Read操作,都是JDBC快。

      2、Hibernate使用uuid.hex构造主键,性能稍微有点损失,但是不大。

      3、Create操作,JDBC在使用批处理的方式下速度比Hibernate快,使用批处理方式耗用JVM内存比不使用批处理方式要多得多。

      4、读取数据,Hibernate的Iterator速度非常缓慢,因为他是每次next的时候才去数据库取数据,这一点从观察任务管理器的java进程占用内存的变化也可以看得很清楚,内存是几十K几十K的增加。

      5、读取数据,Hibernate的List速度很快,因为他是一次性把数据取完,这一点从观察任务管理器的java进程占用内存的变化也可以看得很清楚,内存几乎是10M的10M的增加。

      6、JDBC读取数据的方式和Hibernate的List方式是一样的(这跟JDBC驱动有很大关系,不同的JDBC驱动,结果会很不一样),这 
    从观察java进程内存变化可以判断出来,由于JDBC不需要像Hibernate那样构造一堆Cat对象实例,所以占用JVM内存要比 
    Hibernate的List方式大概少一半左右。

      7、Hibernate的Iterator方式并非一无是处,它适合于从大的结果集中选取少量的数据,即不需要占用很多内存,又可以迅速得到结果。另外Iterator适合于使用JCS缓冲。最终结论:

      由于MySQL的JDBC驱动的重大缺陷,使得测试结果变得毫无意义,不具备任何参考价值,只是我们能够大概判断出一些结论:

      一、精心编写的JDBC无论如何都是最快的。

      二、Hibernate List和Iterator适用的场合不同,不存在孰优孰劣的问题

      我个人认为Hibernate Iterator是JDBC Result的封装,Hibernate List是Scrollable 
    Result的封装,所以我推测,如果在Oracle或者DB2上面做同样的Read测试,如果结果集小于FetchSize,4者在速度上应该都不会有 
    差别;如果结果集大于FetchSize的话,但是不是FetchSize的很多倍,速度排名应该是:

      JDBC Scrollable Result (消耗时间最少) < Hibernate List < JDBC Result < 
    Hibernate Iterator

      如果结果集非常大,但是只取结果集中的部分记录,那么速度排名:

      JDBC Result < Hibernate Iterator < JDBC Scrollable Result < 
    Hibernate List

      为了避免造成误导,我最后强调一下我的结论:

      一、“精心编写”的JDBC一定是性能最好的

      实际上,不管CMP,Hibernate,JDO等等,所有的ORM都是对JDBC的封装,CMP则是一个重量级封装,JDO中度封 
    装,Hibernate是轻量级的封装。从理论上来说,ORM永远也不可能比JDBC性能好。就像任何高级语言的运行性能永远也不会好过汇编语言一个道 理。

      对于Create和Update操作来说,由于普通的Java程序员未必会使用JDBC的Batch的功能,所以Hibernate会表现出超过JDBC的运行速度。

      对于Read的操作来说,ORM普遍都会带有双层缓冲,即PrepreadStatement缓冲和ResultSet缓冲,而JDBC本身没有缓 
    冲机制,在使用连接池的情况下,一些连接池将会提供PrepreadStatement缓冲,有的甚至提供ResultSet缓冲,但是普遍情况 
    下,Java程序员一般都不会考虑到在写JDBC的时候优化缓冲,而且这样做也不太现实,所以在某些情况下,ORM会表现出超过JDBC的Read速度。

      二、Hibernate List和Iterator方式的比较

      JDBC与Hibernate在测试中想要重点考察的方面是 
    List与Iterator,但是由于JDBC驱动问题,结果变的很不可信,不过仍然可以得到一些有用的结论。

      Read操作包括两步:第一步是把数据库的数据取出,构造结果集,把数据放入到结果集中;第二步是遍历结果集,取每行数据。

      List方式是1次性把所有的数据全部取到内存中,构造一个超大的结果集,主要的时间开销是这一步,这一步的时间开销要远远超过JDBC和 
    Iterator方式下构造结果集的时间开销,并且内存开销也很惊人;而对结果集的遍历操作,速度则是非常的惊人(从上面的测试结果来看,30万记录的内 
    存遍历不到100ms,由于这一步不受JDBC影响,因此结果可信)。因此,List方式适合于对结果集进行反复多次操作的情况,例如分页显示,往后往前 
    遍历,跳到第一行,跳到最后一行等等。

      Iterator方式只取记录id到内存中,并没有把所有数据取到内存中,因此构造结果集的时间开销很小,比JDBC和List方式都要少,并且内 
    存开销也小很多。而对结果集的遍历的操作的时候,Iterator仍然要访问数据库,所有主要的时间开销都花在这里。因此,Iterator方式适合于只 
    对结果集进行1次遍历操作的情况,并且Iterator方式特别适合于从超大结果集中取少量数据,这种情况Iterator性能非常好。

      另外Iterator方式可以利用JCS缓冲,在使用缓冲的情况下Iterator方式的遍历操作速度将不受数据库访问速度的影响,得到彻底的提 
    升。Hibernate Iterator JCS方式应该是最快的,Hibernate List速度与JDBC比较接近,而Hibernate 
    Iterator速度还是慢的离谱。另外JDBC和List受到Fetch Size的影响很大,当Fetch 
    Size大于50的时候,速度有非常显著的提升,而Hibernate Iterator的速度似乎不受Fetch Size的影响

    展开全文
  • 消息队列有什么优点缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景? 面试题剖析 为什么使用消息队列 先说一下消息队列常见使用场景吧,其实场景有很多,但是比较核心有 3 个...

    题目

    • 为什么使用消息队列?
    • 消息队列有什么优点和缺点?
    • Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?

    消息中间件各种面试题:
    消息中间件面试题:消息丢失怎么办?
    消息中间件面试题:消息队列的优缺点,区别
    消息中间件面试题:消息中间件的高可用
    消息中间件面试题:如何保证消息的顺序性
    消息中间件面试题:如何保证消息不被重复消费
    消息中间件面试题:如何解决消息队列的延时以及过期失效问题?消息队列满了以后该怎么处理?有几百万消息持续积压几小时呢?
    消息中间件面试题:如果让你写一个消息队列,该如何进行架构设计?

    面试题剖析

    为什么使用消息队列

    先说一下消息队列常见的使用场景吧,其实场景有很多,但是比较核心的有 3 个:解耦异步削峰

    解耦

    看这么个场景。A 系统发送数据到 BCD 三个系统,通过接口调用发送。如果 E 系统也要这个数据呢?那如果 C 系统现在不需要了呢?A 系统负责人几乎崩溃…

    mq-1

    在这个场景中,A 系统跟其它各种乱七八糟的系统严重耦合,A 系统产生一条比较关键的数据,很多系统都需要 A 系统将这个数据发送过来。A 系统要时时刻刻考虑 BCDE 四个系统如果挂了该咋办?要不要重发,要不要把消息存起来?头发都白了啊!

    如果使用 MQ,A 系统产生一条数据,发送到 MQ 里面去,哪个系统需要数据自己去 MQ 里面消费。如果新系统需要数据,直接从 MQ 里消费即可;如果某个系统不需要这条数据了,就取消对 MQ 消息的消费即可。这样下来,A 系统压根儿不需要去考虑要给谁发送数据,不需要维护这个代码,也不需要考虑人家是否调用成功、失败超时等情况。

    mq-2

    总结:通过一个 MQ,Pub/Sub 发布订阅消息这么一个模型,A 系统就跟其它系统彻底解耦了。

    面试技巧:你需要去考虑一下你负责的系统中是否有类似的场景,就是一个系统或者一个模块,调用了多个系统或者模块,互相之间的调用很复杂,维护起来很麻烦。但是其实这个调用是不需要直接同步调用接口的,如果用 MQ 给它异步化解耦,也是可以的,你就需要去考虑在你的项目里,是不是可以运用这个 MQ 去进行系统的解耦。在简历中体现出来这块东西,用 MQ 作解耦。

    异步

    再来看一个场景,A 系统接收一个请求,需要在自己本地写库,还需要在 BCD 三个系统写库,自己本地写库要 3ms,BCD 三个系统分别写库要 300ms、450ms、200ms。最终请求总延时是 3 + 300 + 450 + 200 = 953ms,接近 1s,用户感觉搞个什么东西,慢死了慢死了。用户通过浏览器发起请求,等待个 1s,这几乎是不可接受的。

    mq-3

    一般互联网类的企业,对于用户直接的操作,一般要求是每个请求都必须在 200 ms 以内完成,对用户几乎是无感知的。

    如果使用 MQ,那么 A 系统连续发送 3 条消息到 MQ 队列中,假如耗时 5ms,A 系统从接受一个请求到返回响应给用户,总时长是 3 + 5 = 8ms,对于用户而言,其实感觉上就是点个按钮,8ms 以后就直接返回了,爽!网站做得真好,真快!

    mq-4

    削峰

    每天 0:00 到 12:00,A 系统风平浪静,每秒并发请求数量就 50 个。结果每次一到 12:00 ~ 13:00 ,每秒并发请求数量突然会暴增到 5k+ 条。但是系统是直接基于 MySQL 的,大量的请求涌入 MySQL,每秒钟对 MySQL 执行约 5k 条 SQL。

    一般的 MySQL,扛到每秒 2k 个请求就差不多了,如果每秒请求到 5k 的话,可能就直接把 MySQL 给打死了,导致系统崩溃,用户也就没法再使用系统了。

    但是高峰期一过,到了下午的时候,就成了低峰期,可能也就 1w 的用户同时在网站上操作,每秒中的请求数量可能也就 50 个请求,对整个系统几乎没有任何的压力。

    mq-5

    如果使用 MQ,每秒 5k 个请求写入 MQ,A 系统每秒钟最多处理 2k 个请求,因为 MySQL 每秒钟最多处理 2k 个。A 系统从 MQ 中慢慢拉取请求,每秒钟就拉取 2k 个请求,不要超过自己每秒能处理的最大请求数量就 ok,这样下来,哪怕是高峰期的时候,A 系统也绝对不会挂掉。而 MQ 每秒钟 5k 个请求进来,就 2k 个请求出去,结果就导致在中午高峰期(1 个小时),可能有几十万甚至几百万的请求积压在 MQ 中。

    mq-6

    这个短暂的高峰期积压是 ok 的,因为高峰期过了之后,每秒钟就 50 个请求进 MQ,但是 A 系统依然会按照每秒 2k 个请求的速度在处理。所以说,只要高峰期一过,A 系统就会快速将积压的消息给解决掉。

    消息队列有什么优缺点

    优点上面已经说了,就是在特殊场景下有其对应的好处解耦异步削峰

    缺点有以下几个:

    • 系统可用性降低

      系统引入的外部依赖越多,越容易挂掉。本来你就是 A 系统调用 BCD 三个系统的接口就好了,人 ABCD 四个系统好好的,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整,MQ 一挂,整套系统崩溃的,你不就完了?如何保证消息队列的高可用。

    • 系统复杂度提高

      硬生生加个 MQ 进来,你怎么[保证消息没有重复消费]?怎么[处理消息丢失的情况]?怎么保证消息传递的顺序性?头大头大,问题一大堆,痛苦不已。

    • 一致性问题

      A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

    所以消息队列实际是一种非常复杂的架构,你引入它有很多好处,但是也得针对它带来的坏处做各种额外的技术方案和架构来规避掉,做好之后,你会发现,妈呀,系统复杂度提升了一个数量级,也许是复杂了 10 倍。但是关键时刻,用,还是得用的。

    Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点?

    特性 ActiveMQ RabbitMQ RocketMQ Kafka
    单机吞吐量 万级,比 RocketMQ、Kafka 低一个数量级 同 ActiveMQ 10 万级,支撑高吞吐 10 万级,高吞吐,一般配合大数据类的系统来进行实时数据计算、日志采集等场景
    topic 数量对吞吐量的影响 topic 可以达到几百/几千的级别,吞吐量会有较小幅度的下降,这是 RocketMQ 的一大优势,在同等机器下,可以支撑大量的 topic topic 从几十到几百个时候,吞吐量会大幅度下降,在同等机器下,Kafka 尽量保证 topic 数量不要过多,如果要支撑大规模的 topic,需要增加更多的机器资源
    时效性 ms 级 微秒级,这是 RabbitMQ 的一大特点,延迟最低 ms 级 延迟在 ms 级以内
    可用性 高,基于主从架构实现高可用 同 ActiveMQ 非常高,分布式架构 非常高,分布式,一个数据多个副本,少数机器宕机,不会丢失数据,不会导致不可用
    消息可靠性 有较低的概率丢失数据 基本不丢 经过参数优化配置,可以做到 0 丢失 同 RocketMQ
    功能支持 MQ 领域的功能极其完备 基于 erlang 开发,并发能力很强,性能极好,延时很低 MQ 功能较为完善,还是分布式的,扩展性好 功能较为简单,主要支持简单的 MQ 功能,在大数据领域的实时计算以及日志采集被大规模使用

    综上,各种对比之后,有如下建议:

    一般的业务系统要引入 MQ,最早大家都用 ActiveMQ,但是现在确实大家用的不多了,没经过大规模吞吐量场景的验证,社区也不是很活跃,所以大家还是算了吧,我个人不推荐用这个了;

    后来大家开始用 RabbitMQ,但是确实 erlang 语言阻止了大量的 Java 工程师去深入研究和掌控它,对公司而言,几乎处于不可控的状态,但是确实人家是开源的,比较稳定的支持,活跃度也高;

    不过现在确实越来越多的公司,会去用 RocketMQ,确实很不错(阿里出品),但社区可能有突然黄掉的风险,对自己公司技术实力有绝对自信的,推荐用 RocketMQ,否则回去老老实实用 RabbitMQ 吧,人家有活跃的开源社区,绝对不会黄。

    所以中小型公司,技术实力较为一般,技术挑战不是特别高,用 RabbitMQ 是不错的选择;大型公司,基础架构研发实力较强,用 RocketMQ 是很好的选择。如果是大数据领域的实时计算、日志采集等场景,用 Kafka 是业内标准的,绝对没问题,社区活跃度很高,绝对不会黄,何况几乎是全世界这个领域的事实性规范。

    本文原创地址:https://jsbintask.cn/2019/01/28/interview/interview-middleware-jms/,转载请注明出处。

    展开全文
  • 消息队列有什么优点缺点? Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景? 面试题剖析 为什么使用消息队列 先说一下消息队列常见使用场景吧,其实场景有很多,但是比较核心有 3...
  • JMSAMQP的区别

    2017-11-29 10:48:00
    JMS即Java消息服务(Java Message Service)应用程序接口,是一个Java平台中关于面向消息中间件(MOM)API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关...
  • 消息队列有什么优点缺点?Kafka、ActiveMQ、RabbitMQ、RocketMQ 都有什么区别,以及适合哪些场景?面试题剖析为什么使用消息队列先说一下消息队列常见使用场景吧,其实场景有很多,但是比较核心有 3 个:解耦...
  • 很多小伙伴在学习之前都会去纠结,Java和C++到底有什么区别呢?包括面试时候,面试官也会经常问道Java和C++比,所以没办法!...5: JAVA应用在高层,C++在中间件和底层 6: JAVA离不开业务逻辑,而
  • 登录主要分享JVM、Spring、Spring Boot、Cloud、IDEA、Dubbo、Redis、git、微服务、MySQL、集群、分布式、中间件、消息队列、Linux、网络、多线程、小程序开发、面试题等1、GET与POSTGETPOST是HTTP请求两种基本...
  • 定义:JMS即Java消息服务(JavaMessage Service)应用程序接口是一个Java平台中关于面向消息中间件(MOM)API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。Java消息服务是一个与具体平台无关...
  • 创建 store 方式也会因是否使用中间件而略有区别。未应用中间价之前,创建 store 方式如下: <pre><code> import {createStore} from 'redux'; import reducers from './reducers/index...
  • ETLEAI之间关系与区别

    千次阅读 2009-11-04 10:39:00
    企业业务流程会同时涉及到多个应用系统,因此要求这些系统能够协同,但接口、架构不统一往往使得这些本应紧密集成应用系统成为了一个个“信息孤岛”。于是,企业应用集成(Enterprise Application Integration...
  • 数据库服务器一般都装有数据库如oracle,mssql,...接口服务器是提供给第三方调用服务,主要是为了我们自己应用得安全性,所以我们只把能供给第三方调用东西封装在接口服务器 数据服务器应用服务器有什么...
  •  应用服务器是你应用得服务器,提供应用服务,如你j2ee中间件:基于jboss,weblogic等应用,也可以是自己网络应用服务器,接口服务器是提供给第三方调用服务,主要是为了我们自己应用得安全性,所以...
  • 与传统传输通讯有什么区别? 答:异步,无需等待,消息存放在队列里面。 调用别人的接口时候,返回是同步还是异步? 答:发送请求/响应是同步。 什么是同步?什么是异步? 当A项目调用B接口时,B...
  • 应用服务器是你应用得服务器,提供应用服务,如你j2ee中间件:基于jboss,weblogic等应用,也可以是自己网络应用服务器,接口服务器是提供给第三方调用服务,主要是为了我们自己应用得安全性,所以我们...
  • 消息中间件产生背景 传统Web项目采用http协议基于请求响应传输信息,请求发出后必须等待服务器端响应,如果服务器端不会及时响应客户端会一直等待。 Http协议同步接口调用失败了怎么做? 采用消息补偿...
  • 上一节学到了消息中间件学习笔记五 – ActiveMQ的使用【主题模式】 了解到了 队列模式 与 主题模式 的区别,这一节我们将学习到如何使用Spring集成JMS连接ActiveMQ Spring 提供的接口 ConnectionFactory 用于管理...
  • XA是X/Open DTP组织(X/Open DTP group)定义两阶段提交协议,XA被许多数据库(如Oracle、DB2、SQL Server、MySQL)和中间件等工具(如CICS Tuxedo).本地支持 。XA就是X/Open DTP定义交易中间件与数据库之间...
  • SOAP与CORBA,COM/DCOM的区别

    千次阅读 2010-09-22 17:55:00
    由对象请求代理ORB、对象服务、公共设施、域接口和应用接口这几个部分组成。其核心部分是对象请求代理ORB(Object Request Broker)。ORB提供了一种机制,通过这种机制,对象可以透明发出请求接收响应。分布、...
  • 讲讲jdk1.71.8的区别? 几种内置的线程池 什么是原子性,可见性,有序性?说几个常用的锁接口实现锁。 MySQL的事务隔离级别以及MVCC机制 Redis的缓存雪崩,缓存穿透以及如何解决? 分布式架构简单介绍 CMS收集器...
  • 一、数据结构与算法基础 · 说一下几种常见的排序算法分别的... · 接口与抽象类的区别? · Java中的异常有哪几类?分别怎么使用? · 常用的集合类有哪些?比如List如何排序? · ArrayListLinkedList...
  • 一、数据结构与算法基础 · 说一下几种常见的排序算法分别的复杂度。 · 用Java写一个冒泡...· 接口与抽象类的区别? · Java中的异常有哪几类?分别怎么使用? · 常用的集合类有哪些?比如List如何排序? ...

空空如也

空空如也

1 2 3 4 5 6
收藏数 106
精华内容 42
关键字:

中间件和接口的区别