我开始学习Scala和函数式编程.我正在读这本书!编程scala:解决Java虚拟机上的多核复杂性".在第一章我看到了事件驱动的并发和Actor模型这个词.在我继续阅读本书之前,我希望有一个关于事件驱动的并发或Actor模型的想法.
什么是事件驱动的并发性,它与Actor模型有什么关系?
我一直在阅读一些NodeJs文章,以了解它的异步性质,在此期间我发现了这个并且非常喜欢它Node.js,Doctor's Offices and Fast Food Restaurants - 了解事件驱动编程
有一种叫做EventLoop
基于FIFO的队列.他们说当异步函数被击中时,它会被放到EventLoop并继续在那里执行.
我在这里有点困惑.例如,这里说:
实际上,setTimeout和setInterval等异步函数被推送到称为事件循环的队列中.
在同一篇文章中:
Event Loop是一个回调函数队列.执行异步函数时,回调函数将被推入队列.在执行异步函数之后的代码之前,JavaScript引擎不会开始处理事件循环.
但它与此图像不同:
我们来看下面的例子:
console.log("Hello,");
setTimeout(function(){console.log("World");},0);
Run Code Online (Sandbox Code Playgroud)
从我从那些不同的解释中理解的,
function(){console.log("World");}
的是setTimeout()
函数的一部分,即回调,将放在EventLoop中.一旦setTimeout
完成,它也将执行EventLoop
.setTimeout(function(){console.log("World");},0);
将被放到EventLoop并将被执行...我现在更加困惑了.它应该是简单的东西,但我想一个好但简单的解释对我来说对以下问题很好:
我只是试图让我的头脑围绕事件驱动的JS,所以请耐心等待我.我的应用程序中有不同类型的模块.有些只是封装数据,有些则管理DOM的一部分.有些模块依赖于其他模块,有时一个模块依赖于多个其他模块的状态,但我不希望它们直接通信或将一个模块传递给另一个模块以便于访问.我试图创建最简单的场景来说明我的问题(实际的模块当然要复杂得多):
我有一个dataModule只暴露一些数据:
var dataModule = { data: 3 };
Run Code Online (Sandbox Code Playgroud)
有一个configModule公开了用于显示该数据的修饰符:
var configModule = { factor: 2 };
Run Code Online (Sandbox Code Playgroud)
最后有一个displayModule,它结合并呈现来自其他两个模块的数据:
var displayModule = {
display: function(data, factor) {
console.log(data * factor);
}
};
Run Code Online (Sandbox Code Playgroud)
我也有一个简单的pub-sub实现,所以我可以像这样在模块之间进行调解:
pubsub.subscribe("init", function() {
displayModule.display(dataModule.data, configModule.factor);
});
pubsub.publish("init"); // output: 6
Run Code Online (Sandbox Code Playgroud)
然而,这种方式我似乎最终得到了一个必须明确知道所有模块实例的中介 - 有没有办法避免这种情况?如果这些模块有多个实例,我也不知道这是如何工作的.避免全局实例变量的最佳方法是什么?我想我的问题是管理类似的东西最灵活的方法是什么?我是在正确的轨道上,还是这完全错了?很抱歉我的问题不是很准确,我只需要有人帮我推进正确的方向.
我想澄清组织架构的最佳方式是什么。
我有休息 api 和微服务架构。我已经应用了每个服务模式的数据库。
所以让我们想象一下用户想要创建一个订单(一个电子商务系统)。但是用户可以有信用额度。所以流程如下:
OrderService 创建一个挂单。然后推送一个关于它的事件。
UserService 处理该事件并发布超出信用额度事件或信用保留事件。
OrderService 接收事件并将订单的状态更改为已批准或已取消。
一切看起来都不错。但问题是用户在这个简单的流程中会做什么?我的意思是:用户发出 POST 请求 /orders 和 ...
不幸的是,上面的任何选项都有其优点和缺点。
挑战在于我描述了最简单的情况。实际上,可能涉及数十个服务(甚至第三方)。当然,我期待高负载。所以队列可能被填满。
请提出解决方案进行讨论。我非常感谢答案以及指向生产就绪系统文档的链接。
我最近开始随意使用tkwait并注意到某些功能仅在特殊条件下才起作用。例如:
import tkinter as tk
def w(seconds):
dummy = tk.Toplevel(root)
dummy.title(seconds)
dummy.after(seconds*1000, lambda x=dummy: x.destroy())
dummy.wait_window(dummy)
print(seconds)
root = tk.Tk()
for i in [5,2,10]:
w(i)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
上面的代码工作得很好并且符合预期:
但在事件驱动的环境中,这些tkwait
调用会变得很棘手。该文档指出引用:
如果事件处理程序再次调用 tkwait,则对 tkwait 的嵌套调用必须在外部调用完成之前完成。
>>5
>>2
>>10
您将得到的不是输出>>10
>>2
>>5
,因为嵌套调用会阻塞内部调用,而外部调用会阻塞内部调用。我怀疑嵌套事件循环或等效的主循环在等待时以正常方式处理事件。
我使用此功能是否做错了什么?因为如果您仔细想想,几乎所有 tkinter 对话框窗口都在使用此功能,而我以前从未读过此行为。
事件驱动的示例可能是:
import tkinter as tk
def w(seconds):
dummy = tk.Toplevel(root)
dummy.title(seconds)
dummy.after(seconds*1000, lambda x=dummy: x.destroy())
dummy.wait_window(dummy)
print(seconds)
root …
Run Code Online (Sandbox Code Playgroud) 我知道node.js被称为在V8 Javascript引擎上托管的"事件驱动的I/O"服务器端javascript .我访问了node.js网站,然后阅读了wikipedia条目,但是不能完全了解在哪里使用它以及它将如何有用."事件驱动的IO"?"V8 Javascript引擎"?在某些情况下,我看到使用"服务器端"javascript有点矫枉过正.我在node.js的维基百科条目中使用了这段代码:
var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end('Hello World\n');
}).listen(8000);
console.log('Server running at http://127.0.0.1:8000/');
Run Code Online (Sandbox Code Playgroud)
我一直在想,运行服务器真的有一个重要的目的,特别是服务于应用程序前端部分执行的javascript文件吗?
我还在github中分叉了node.js repo以了解它的工作原理,结果发现它的一些模块是用C++编写的.那么它毕竟不是一个JavaScript?
有人可以给我一个清楚的解释吗?对不起,如果问题不明确或者其他什么,我只是一个初学者.将欣赏任何意见/建议.谢谢
最近,我开始学习Node.js的,对自己的无阻塞IO和令人难以置信的速度见长的V8之上的JavaScript库.
据我了解,节点不等待IO的响应,但运行的事件循环(类似于游戏循环),保持检查未完成的操作,并继续/尽快IO响应完成它们.节点性能与Apache的HTTPD与节点是显著更快,同时使用更少的内存.
现在,如果你了解了Apache,你了解它每个用户使用1个线程,这理应减缓下来显著,这是出现在我的问题,其中:
如果将线程与事件循环内部节点进行比较,则会开始看到相似之处:两者都是等待资源响应的未完成进程的抽象,都检查操作是否定期进行,然后不占用CPU占用了一段时间(至少我认为一个好的阻塞API在重新检查之前会休眠几毫秒).
现在哪个突出的,关键的差异让线程变得更糟?
我有一种情况,我调用外部API A并使用其响应来提供API B的请求并调用它,然后将响应返回给API A的调用者.如下所示
method(){
response = call API A
}
method_for_API_A(){
handler() ->{
API_B
}
return response;
}
method_for_API_B(){
//code to call API B
}
Run Code Online (Sandbox Code Playgroud)
我在这里面临的是API A方法返回响应而不等待从B获得响应.
我检查了vert.x的executeBlocking方法,并尝试使用'阻塞队列',但无法实现我打算做的事情.有人可以指导我做正确的方法.谢谢.
编辑:只是解释确切的情况
Class MyClass{
public Response method_A (Request request){
String respFromApiA = Call_API_A(request) ; // STEP 1
Response respFromApiB = Call_API_B(request, respFromApiA); // STEP 2
Print(respFromApiB) // PRINT FINAL Response
return respFromApiB; // STEP 3
}
String Call_API_A(Request request){
// Implementation
Print(string); // PRINT API A response
return string
}
Response Call_API_B(Response …
Run Code Online (Sandbox Code Playgroud) 我们有一条数据处理管道,可在其中接收来自不同来源的数据。整个管道是通过使用事件驱动的体系结构和微服务来实现的。服务之一具有三个单独的任务。其中两个在不同的数据源之间是完全相同的,但是第三个任务范围可能会根据我们的数据源是什么而略有变化。例如,对于一个源,可以基于文件1和文件2计算唯一签名,对于另一个源,可以根据字段2和3计算唯一签名。实现此服务的最佳方法是如何与微服务粒度原则保持一致?
我想到了三种方法:
1)创建一个服务,并对每个源使用不同的实现(例如工厂设计模式)。根据来源,将在运行时使用其中一种实现。
优点:服务数量少。复杂度降低
缺点:由于该服务将在所有数据源之间共享,因此,通过添加任何新的数据源,应重新部署该服务,这将在该服务与负责从源收集数据的任何服务之间创建隐式依赖关系。
2)将此服务分为两个服务,对所有源使用一个,然后重新实现每个数据源的提取服务。
优点:收集器与这两个服务之间没有依赖性。通过添加新的源,需要实施新的服务,并且不需要重新部署与其他源相关的服务。
缺点:更多的服务,并且由于服务太小,我们将来可能会面临纳米服务的问题。
3)不要更改服务的粒度,而是在运行时创建服务的不同实例。每个都有不同的配置,以指定用于每个源的字段集。在这种情况下,代码是共享的,但是运行时实例根据它属于哪个源而有所不同。
优点:服务数量少,没有操作依赖性
缺点:将逻辑的复杂性转移到运行时,这可能使部署和操作更具挑战性
在线有许多基于线程的Web服务器示例,但我还没有真正看到任何能够提供基于事件循环的良好示例(没有非常复杂,例如lighttp和nginx).
有吗?如果没有,我应该阅读/看看什么来帮助我学习如何制作这种服务器?(这包括C中的异步IO等)
我已经理解了基于事件循环的编程如何工作的基础知识,特别是在像Python这样的高级语言中,但我需要能够在C中实现一个.
event-driven ×10
events ×3
javascript ×3
event-loop ×2
node.js ×2
architecture ×1
asynchronous ×1
c ×1
c++ ×1
concurrency ×1
evented-io ×1
java ×1
python ×1
rest ×1
saga ×1
scala ×1
tcl ×1
tkinter ×1
vert.x ×1
wait ×1