文档章节

异步转同步

xpbug
 xpbug
发布于 2016/03/02 19:34
字数 875
阅读 185
收藏 3

下面是一个CS架构的部署, 服务端是SEDA类型的架构,消息传输完全是异步。而客户端在使用SDK向服务端发起请求。为了方便客户的使用,我们希望能提供同步方式的SDK。所以我们的SDK需要将异步消息转换成同步消息。如何做到这一点呢?

因为服务器需要保持CPU的充分利用,所以异步转同步的工作不应该由Server完成,而应该有SDK来完成。简单的讲,异步转同步的流程应该分成这么几个步骤:

  1. SDK发出请求

  2. SDK等待返回

  3. 服务端持续返回消息

  4. 返回的消息和请求匹配上

  5. SDK返回响应

把以上的步骤封装在SDK里面,上面的示意图可以演变为下面的图

在实现中,requestNo和Waiter是实现的关键。RequestNo使发出的请求和返回的响应能够匹配上,而Waiter则可以使SDK等待,当拿到响应以后,唤醒SDK,返回响应。

略微解释一下上图的流程:

  1. Client调用Sender准备发请求。Sender先生成一个requestNo,将requestNo贴到请求上。然后生成一个waiter,将requestNo和waiter放入Map中。Map中存有所有正在等待消息返回的waiter。然后Sender阻塞在waiter的standby(timeout)方法上。

  2. Sender将消息塞入发送队列。

  3. Connection从发送队列取出消息。

  4. Connection发消息给Server。

  5. Server持续异步返回各类消息。

  6. Connection将返回的消息放入接收队列。

  7. Receiver从接收队里中取出消息。

  8. Receiver从消息中获取requestNo,然后从Map中获取相应的waiter。并调用waiter的accept( )方法。

  9. Waiter接受了消息,并确认成功接收到所有的响应消息。唤醒Sender。

  10. Sender返回消息给client。

public class Sender {
    public IObject send(IObject request, long timeout) {
        String requestNo = getRequestNo();
        waiter = new Waiter(client, requestNo);
        client.waiters.put(requestNo, waiter);
        request.set("requestNo", requestNo);
        connection.send(request);
        waiter.standby(timeout);  // Block
        int state = waiter.getState(); // 0=waiting first, 1=waiting next, 2=timeout, 3=complete
        if (state == 3) {
            return waiter.getResult();
        } else {
            // create new response for failure.
        }
    }
}

public class Receiver {
    public void receive(IObject msg) {
        String requestNo = node.get("requestNo");
        Waiter waiter = client.waiters.get(requestNo);
        if (waiter != null) {
            if (waiter.accept(msg)) return;
        }
        // 如果消息不被接受,则发给MessageHandler来处理。        
        if (client.handler != null) {
            client.handler.handleMessage(msg);
        }
    }
}

public class Waiter {
    // 0=waiting first; 1=waiting second; 2=timeout; 3=complete 
    private int state=0;
    private List<IObject> messages;
    
    public synchronized void standby(long timeout) {
        try {
            this.wait(timeout);
        } catch (InterruptedException e) {
        }
        if (state < 2) {
            state = 2;
            client.waiters.remove(requestNo);
        }
    }
 
    public synchronized boolean accept(IObject msg) {
        if (state >= 2) {
            // waiter is closed
            return false;
        } 
         
        try {
            if (state == 0) {
                // 收到第一个返回的消息
                messages.add(msg)
                // 查看是否还有后续消息
                // 设置state的状态
                // 如果需要后续消息, return true
            }
            if (state == 1) {
                // 如果不是期待的消息类型, return false
                // 收到了后续消息
                messages.add(msg)
                // 设置状态
                // 如果需要后续消息, return true
            }
            state = 3;
            client.waiters.remove(requestNo);
            // 唤醒SDK
            this.notifyAll();
            return true;
        } catch (Exception e) {
            // 发生解析错误, 创建错误消息
            messages.add(err)
            state = 3;
            client.waiters.remove(requestNo);
            this.notifyAll();
            return true;
        } 
    }
    
    public synchronized IObject getResult() {
        // 将message列表中的消息合并成一个result
        return result;
    }
}


© 著作权归作者所有

共有 人打赏支持
xpbug
粉丝 303
博文 102
码字总数 125336
作品 0
浦东
程序员
私信 提问
关于Alipay支付宝接口(Java版)下

4.alipay 页面跳转同步通知处理 4.1 页面跳转同步通知   当买家完成了支付流程后,会出现成功支付的页面,该页面做短暂停留后,会跳转到我们AlipayConfig.xml中的 return_url 属性所指定的...

站在云端er
2016/08/22
20
0
java支付宝和微信的移动支付,扫码支付后台开发

[主要内容] 按照官方提供的SDK开发支付后端 仅限JAVA语言的服务端开发 支付宝移动支付构建移动端需要的参数和签名,支付宝异步通知方法 支付宝网站扫码支付,完成异步通知和同步跳转 微信移动...

互联网-民工
2016/05/30
6
0
ajax 同步和异步的区别|已迁移

同步会阻塞后面的代码,也就是说假设这个ajax请求要3 5秒,浏览器就会阻塞住3 5秒不执行后面的,知道等到ajax请求完成。 而且同步不能直接使用jsonp。 异步不能在回调之外直接拿到返回的dat...

辣条拌鱼翅
2015/07/20
0
0
微信支付和支付宝支付

[主要内容] 按照官方提供的SDK开发支付后端 仅限JAVA语言的服务端开发 支付宝移动支付构建移动端需要的参数和签名,支付宝异步通知方法 支付宝网站扫码支付,完成异步通知和同步跳转 微信移动...

黔中伯爵
2016/06/04
2
0
java 异步查询转同步多种实现方式:循环等待,CountDownLatch,Spring EventListener

异步转同步 业务需求 有些接口查询反馈结果是异步返回的,无法立刻获取查询结果。 正常处理逻辑 触发异步操作,然后传递一个唯一标识。 等到异步结果返回,根据传入的唯一标识,匹配此次结果...

叶止水
2018/08/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linux-tao
39分钟前
0
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linuxprobe16
今天
9
0
OSChina 周日乱弹 —— 没时间 没头发 但有钱

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @开源中国总经办主任 :分享齐一的单曲《这个年纪》 《这个年纪》- 齐一 手机党少年们想听歌,请使劲儿戳(这里) @肿肿卷 :我真的可以睡一天...

小小编辑
今天
90
6
Django进阶 1.1 ORM基础—ORM 1.2.1 增删改查之查询 1.2.2 删改增 (1) 1.2.3 删改增 (2)

ORM基础 ORM是Django操作数据库的API,Django的作者将sql语句封装在里面供我们使用。 我们前面还提到过Django提供一个模拟数据库的工具,sqlite,供我们学习测试使用。 如果我们想使用mysql...

隐匿的蚂蚁
今天
3
0
Windows 上安装 Scala

在安装 Scala 之前需要先安装 Java 环境,具体安装的详细方法就不在这里描述了。 您可以自行搜索我们网站中的内容获得其他网站的帮助来获得如何安装 Java 环境的方法。 接下来,我们可以从 ...

honeymose
今天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部