文章目录
- 1.异步
-
- [1.1 调用异步](#1.1 调用异步)
- [1.2 流程异步](#1.2 流程异步)
- [1.3 数据流异步](#1.3 数据流异步)
- [1.4 小结](#1.4 小结)
- 2.并发
-
- [2.1 请求并发](#2.1 请求并发)
- [2.2 冗余请求](#2.2 冗余请求)
- [2.3 小结](#2.3 小结)
- 参考文献
1.异步
对于处理耗时长的任务,如果采用同步等待的方式,会严重降低系统的吞吐量,可以采用异步化进行解决。
异步(Asynchronous)是一种编程模型或执行方式,在这种方式中,任务的启动和完成不是同步的,也就是说,程序不会在等待任务完成时阻塞,而是可以继续执行其他操作。当异步任务完成时,程序会通过回调、通知或事件的方式获取结果或处理后续操作。
1.1 调用异步
异步调用发生在使用异步编程模型来提高代码效率的时候,实现方式主要有:
- Callback
异步回调通过注册一个回调函数,然后发起异步任务,当任务执行完毕时会回调用户注册的回调函数,从而减少调用端等待时间。这种方式会造成代码分散难以维护,定位问题也相对困难。
- Promise 和 Future
当用户提交一个任务时会立刻先返回一个Future,然后任务异步执行,后续可以通过 Future 获取执行结果。
JavaScript 中的 Promise 和 Java 中的 CompletableFuture 都是常见的异步处理方式。
js
// 使用 Promise 处理异步操作
let promise = new Promise((resolve, reject) => {
// 模拟异步操作
setTimeout(() => resolve('Operation complete'), 1000);
});
promise.then(result => console.log(result)); // 输出: "Operation complete"
- Async/Await
Async/Await 是对 Promise 的进一步封装,提供了更简洁、更易读的异步代码写法。使用 async 标记的函数会返回一个 Promise,而 await 关键字用于暂停函数的执行,直到 Promise 处理完成。
JavaScript 和 Python 都支持 async/await 语法。
js
async function fetchData() {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
}
fetchData();
- 事件驱动
事件驱动模型常用于 GUI 编程和服务器端编程,通过事件触发异步操作的处理。
比如 Node.js 通过事件驱动模型来处理异步 I/O 操作。
js
const EventEmitter = require('events');
const eventEmitter = new EventEmitter();
// 定义事件处理程序
eventEmitter.on('dataReceived', (data) => {
console.log('Data received:', data);
});
// 模拟异步数据接收
setTimeout(() => eventEmitter.emit('dataReceived', 'Sample Data'), 1000);
可以对多个异步编程进行编排,组成更复杂的异步处理,并以同步的代码调用形式实现异步效果。
CPS 将后续的处理逻辑当作参数传递给 Then 并可以最终捕获异常,解决了异步回调代码散乱和异常跟踪难的问题。Java 中的 CompletableFuture 和 C++ PPL(Parallel Patterns Library)基本支持这一特性。典型的调用形式如下:
cpp
void handleRequest(const Request &req) {
return req.Read().Then([](Buffer &inbuf){
return handleData(inbuf);
}).Then([](Buffer &outbuf){
return handleWrite(outbuf);
}).Finally(){
return cleanUp();
});
}
关于 CPS 更多信息推荐阅读:2018 中国 C++ 大会的吴锐_C++服务器开发实践部分。
调用异步是一种异步编程模型,通过允许任务非阻塞地执行,使程序在等待某些操作(如 I/O 操作)完成的同时,能够继续处理其他任务,从而提高并发性和性能。常见的实现方式包括回调函数、Promise/Future、Async/Await,以及事件驱动模型等。
1.2 流程异步
一个业务流程往往伴随着调用链路长、后置依赖多等特点,导致业务流程处理耗时长,降低了系统的可用性和并发处理能力。
同步改异步,可以降低主链路的处理耗时。
举个例子,比如我们去 KFC 点餐,遇到排队的人很多,当点完餐后,大多情况下我们会隔几分钟就去问好了没,反复去问了好几次才拿到,在这期间我们也没法干活了。
这个就叫同步轮训,这样效率太低了。
服务员被问烦了,就在点完餐后给我们一个号码牌,每次准备好了就会在服务台叫号,这样我们就可以在被叫到的时候再去取餐,中途可以继续干自己的事。这就叫异步。
当一个微服务需要处理大量的请求或任务时,直接处理这些任务可能导致服务压力过大。通过消息队列(如 Kafka、RabbitMQ、RocketMQ 等)对耗时的任务进行异步化。
微服务将任务消息发送到消息队列中,另一个处理服务从队列中取出任务异步处理。这样可以解耦服务,提升系统的弹性和扩展性。
1.3 数据流异步
处理大量实时数据流(如日志数据、传感器数据)。
使用流处理框架(如 Apache Flink、Spark Streaming)来异步处理数据流。数据被实时处理和分析,结果可以用于实时监控和决策。
1.4 小结
在微服务架构中,异步处理可以显著提高系统的性能和扩展性。通过异步编程模型、消息队列、数据流异步处理,微服务可以更高效地处理并发请求、管理任务和优化资源利用。异步编程不仅提升了系统的响应速度,还增强了系统的灵活性和可扩展性。
2.并发
在微服务架构中,并发处理是提升系统性能和响应能力的关键技术。并发使得系统能够同时处理多个任务或请求,显著提高吞吐量和资源利用率。
2.1 请求并发
如果一个任务需要处理多个子任务,可以将没有依赖关系的子任务并发化,这种场景在后台开发很常见。
如一个请求需要查询 3 个数据,分别耗时 T1、T2、T3,如果串行调用总耗时 T=T1+T2+T3。对三个任务执行并发,总耗时 T=max(T1,T 2,T3)。同理,写操作也如此。对于同种请求,还可以同时进行批量合并,减少 RPC 次数。
2.2 冗余请求
冗余请求指同时向后端服务发送多个同样的请求,谁响应快就是使用谁,其他的则丢弃。
这种策略缩短了主调方的等待时间,但也使整个系统调用量猛增,一般适用于初始化或者请求少的场景。比如腾讯的移动连通服务维纳斯(WNS,Wireless Network Service)的跑马模块其实就是这种机制,跑马模块为了快速建立长连接同时向后台多个 IP/Port 发起请求,谁快就用谁,这在弱网的移动设备上特别有用,如果使用等待超时再重试的机制,无疑将大大增加用户的等待时间。
这种方式较少使用,知道即可。
2.3 小结
并发在微服务架构中通过多线程/多进程、异步 I/O、并行计算和流处理等方式,显著提升了系统的处理能力和性能。它能够有效地处理大量并发请求和数据流,优化资源利用率,并提高系统的响应速度和吞吐量。通过合理应用并发技术,微服务系统可以更好地应对高负载和高并发的挑战。