目前,公司技术规划要求未来所有的服务要全面实现异步化接口,使得每个服务能达到1万/秒的单机性能。我们知道,在一个服务请求中,可能会调用其他服务,还会使用memcache、kv以及mysql等。目前,大众点评的使用的服务框架、kv和cache框架均有异步化调用的接口,但是唯独缺少异步调用数据库的框架支持。这就意味着,如果业务代码一旦其他的请求都异步化了,但是唯独数据库还是同步的,那么就没有达成完全的异步化。在这种情况下,就要求必须有异步化数据库调用的框架支持。zebra-dao就是在这种情况下开发的。

异步化DAO的设计和实践

1. 背景

目前,公司技术规划要求未来所有的服务要全面实现异步化接口,使得每个服务能达到1万/秒的单机性能。我们知道,在一个服务请求中,可能会调用其他服务,还会使用memcache、kv以及mysql等。目前,大众点评的使用的服务框架、kv和cache框架均有异步化调用的接口,但是唯独缺少异步调用数据库的框架支持。这就意味着,如果业务代码一旦其他的请求都异步化了,但是唯独数据库还是同步的,那么就没有达成完全的异步化。在这种情况下,就要求必须有异步化数据库调用的框架支持。zebra-dao就是在这种情况下开发的。

2. 技术选型

调研了目前所有的异步化方案,考虑到有以下的实现:

  1. 业务使用时自己将每一次的dao调用放到异步线程池中去。优点是,不需要架构支持什么。缺点是,因为是业务迁移,迁移的代价比较大。

  2. 使用google的async-mysql-connector。优点是:背后实现是基于NIO的方式,性能更高。缺点是,异步的jdbc接口上层没有任何的DAO框架支持,公司业务基本无法使用。

所以,笔者主要考虑到业务的易用性和方便迁移,决定将方案定为在MyBatis-Spring的基础上进行封装,背后实现是线程池的方式。

3. API

zebra-dao目前支持两种方式的异步API:回调和Future接口方式,对于每一个异步接口,必须要有相应的同步方法定义,因为其实所有的异步接口最后还是在线程池中调用的同步接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface UserMapper {
    /**
    * Normal synchronization dao method.
    */
    public UserEntity findUserById(@Param("userId"int userId);
 
    /**
    * Asynchronous callback method. Return void and only one
    * callback method required.
    */
    public void findUserById(@Param("userId"int userId, AsyncDaoCallback<UserEntity> callback);
     
    /**
    * Asynchronous future method. Return future and must have the 
    * same params as synchronization method.
    */
    @TargetMethod(name = "findUserById")
    public Future<UserEntity> findUserById1(@Param("userId"int userId);
}

业务如果使用的是回调接口,那么在使用的时候必须定义回调方法,在回调方法中,通常做的是把结果放到服务框架的异步回调方法中,这样才能做到一个服务的全部异步化。在下面的例子的回调方法中,隐去了使用服务异步调用接口的具体实现,仅仅展示如何定义回调方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
dao.findUserById(1new AsyncDaoCallback<UserEntity>() {
    @Override
    public void onSuccess(UserEntity user) {
        System.out.println(user);
 
        //another asynchronous invoke in the asynchronous invoke
        dao.findUserById(2new AsyncDaoCallback<UserEntity>() {
            @Override
            public void onSuccess(UserEntity user) {
                System.out.println(user);
            }
 
            @Override
            public void onException(Exception e) {
            }
        });
 
        //synchronization invoke in the  asynchronous invoke
        UserEntity entity = dao.findUserById(3);
        System.out.println(entity);
    }
 
    @Override
    public void onException(Exception e) {
    }
});

对于使用的Future接口,就和使用Future一样,没有额外特别之处。

1
2
3
Future<UserEntity> future = dao.findUserById1(1);
UserEntity user = future.get();
System.out.println(user);

更详细的使用方法,请参考这里

4. 总结

目前,公司的价格服务等一系列的服务使用的这个框架去访问数据库,这些服务也因此实现了异步化。未来,公司会将越来越多的服务使用这个框架。目前,这个框架还额外实现了物理分页的功能。这个功能的API的设计也很多为了兼容已有业务代码考虑的。

异步化DAO的设计和实践的更多相关文章

  1. 商品详情页系统的Servlet3异步化实践

    http://jinnianshilongnian.iteye.com/blog/2245925 博客分类: 架构   在京东工作的这一年多时间里,我在整个商品详情页系统(后端数据源)及商品详情页统一 ...

  2. 使用异步任务降低API延迟_实践总结

    之前在想如何降低API的延迟,这些API里有几个比较耗时的操作且是串行执行,那通过异步执行的方式理论上可以降低运行的时间,如下图所示: 具体的实现比较简单,例如这样: public class Par ...

  3. 唯品会API网关设计与实践--转

    原文地址:https://609518.kuaizhan.com/86/70/p4108366952248f 刘璟宇Leo 唯品会资深研发工程师,在大型高性能分布式系统设计和开发方面有丰富的经验.目前 ...

  4. Apache Beam实战指南 | 大数据管道(pipeline)设计及实践

    Apache Beam实战指南 | 大数据管道(pipeline)设计及实践  mp.weixin.qq.com 策划 & 审校 | Natalie作者 | 张海涛编辑 | LindaAI 前 ...

  5. vivo商城促销系统架构设计与实践-概览篇

    一.前言 随着商城业务渠道不断扩展,促销玩法不断增多,原商城v2.0架构已经无法满足不断增加的活动玩法,需要进行促销系统的独立建设,与商城解耦,提供纯粹的商城营销活动玩法支撑能力. 我们将分系列来介绍 ...

  6. RESTful API 设计最佳实践

    背景 目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个"万能"的设计标准:如何鉴权?API ...

  7. AppBox升级进行时 - 扁平化的权限设计

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. AppBox v2.0中的权限实现 AppBox v2.0中权限管理中涉及三个 ...

  8. ****RESTful API 设计最佳实践(APP后端API设计参考典范)

    http://blog.jobbole.com/41233/ 背景 目前互联网上充斥着大量的关于RESTful API(为方便,下文中“RESTful API ”简写为“API”)如何设计的文章,然而 ...

  9. RESTful API 设计最佳实践(转)

    摘要:目前互联网上充斥着大量的关于RESTful API(为了方便,以后API和RESTful API 一个意思)如何设计的文章,然而却没有一个”万能“的设计标准:如何鉴权?API格式如何?你的API ...

随机推荐

  1. JAVA联调接口跨域解决办法

    JAVA联调接口跨域解决办法 第一种代码: HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1,HttpStatus. ...

  2. [Cycle.js] The Cycle.js principle: separating logic from effects

    The guiding principle in Cycle.js is we want to separate logic from effects. This first part here wa ...

  3. hdu1015(Safecracker )

    Problem Description === Op tech briefing, 2002/11/02 06:42 CST === "The item is locked in a Kle ...

  4. Javascript基础form表单

    <!DOCTYPE HTML> <html> <head> <script type="text/javascript" charset= ...

  5. 自定义VS的ItemTemplates 实现任意文件结构

    上一篇说到重写IHttpHandler实现前后端分离,这次说一下如何建立一个如下文件结构. VS建立webform时是根据模板来的.C#的模板目录如下: F:\Program Files (x86)\ ...

  6. JS如何得到Repeater中TextBox控件的值

    var subsidylCost = document.getElementById("txtSubsidylCost.ClientID").value; 这样获取不到,因为txt ...

  7. js 计算两个日期之间的月数

    //返回两个日期相差的月数 function MonthsBetw(date1, date2) { //用-分成数组 date1 = date1.split("-"); date2 ...

  8. OpenGL ES 2.0 符点精度

    片元着色器中使用符点相关类型的变量时与顶点着色器中有所不同,在顶点着色器中直接声明使用即可,而在片元着色器中必须指定精度. lowp 低 mediump 中 highp 高 指定整个着色器中符点相关类 ...

  9. ifstream中文路径问题分析

    最近维护一个项目,遇到了ifstream在中文路径下打开文件失败的bug,我搜索了一下,最后整理成下文以后日后查阅. 一.问题重现 vs2008下创建一个简单win32工程. 使用ANSI编码方式:项 ...

  10. Java学习笔记——可视化Swing中JTable控件绑定SQL数据源的两种方法

    在 MyEclipse 的可视化 Swing 中,有 JTable 控件. JTable 用来显示和编辑常规二维单元表. 那么,如何将 数据库SQL中的数据绑定至JTable中呢? 在这里,提供两种方 ...