sogou / workflow

C++ Parallel Computing and Asynchronous Networking Framework
Apache License 2.0
13.07k stars 2.41k forks source link

关于tutorial-05-http_proxy的一些问题 #1606

Closed HT-Sun closed 2 months ago

HT-Sun commented 2 months ago

你好。你还是代码看得比较仔细的。前面几个回调函数的时机描述都没有问题。

reply_callback()是server task的callback。server task和client task都是WFHttpTask类型,callback的时机也是一样的,都是在http请求交互完成之后。对于server task来讲,就是把reply写完整写入tcp send buffer。当然,还有一种情况是失败了。

所以,reply_callback的主要目的就是看回复成功了没有。并且,server task在callback之后,还可以继续向series里放入新的任务的。例如加一个上报请求状态给监控服务器的网络任务。

调用顺序:process->http_callback->reply_callback->series_callback。

你好,刚开始学习网络编程,对于回调做法非常困惑,所以我仍旧有很多问题。

  1. 在proxy server调用process过程时,存在一个proxy_task,这个任务时如何产生的。上述的server task指的是不是就是这个proxy_task。从角色上看,proxy_task是proxy server为client提供服务的,所以会被称作server task?

  2. proxy_task存在于一个series中,process过程创建了一个向web server请求的http_task,并将该任务追加在当前proxy_task所在的series。在process执行完毕时,proxy_task中的resp仍旧是初始化状态,完全没有能力完整写入tcp send buffer。

  3. 由于series中出现了新的任务http_task(proxy server通过该任务向web server请求服务,所以被称为client task?),在接收到web server的回复后,触发http_callback回调。在执行http_task到触发回调的过程中,proxy_task的状态是暂用线程等待还是被挂起了。

  4. 在http_callback触发开始执行后,通过series的上下文更新了proxy_task中的resq,此时对于proxy_task而言,写入tcp send buffer的条件已经具备,写入的过程是如何触发的。

  5. 我的理解是:proxy_task->process->http_task->http_callback->proxy_task->reply_callback->series_callback?但是这里面应该有多线程才对,对于这个series任务流而言,线程是如何切换的?

Originally posted by @HT-Sun in https://github.com/sogou/workflow/issues/1537#issuecomment-2288838622

Treston-W commented 2 months ago

朋友,我从业务逻辑上分享一下我的理解~:

  1. 我们可以理解为有三个角色:client -> proxy_server -> remote_server
  2. proxy_server负责把client的请求转发给remote_server,并负责把remote_server的回复转发给client
  3. proxy_task相当于连接client-proxy_server,process()是proxy_server收到client请求后执行的函数,proxy_task->get_req()已包含客户端请求的所有信息
  4. process()退出后,相当于http_task触发了,即proxy_server会向remote_server发送数据
  5. http_task相当于连接proxy_server-remote_server,http_callback()是proxy_server收到remote_server回复后执行的函数,task->get_resp()已包含remote_server回复的所有信息
  6. reply_callback()是proxy_server回复完client之后执行的函数
  7. series_callback()是整个series内的task全结束后执行的函数
Barenboim commented 2 months ago

1、server task就是proxy task。因为这个例子是proxy,所以就叫proxy task了。这个任务是收到client发过来的请求时创建的。http server的任务,最终会在这里创建: https://github.com/sogou/workflow/blob/5766424c4d08e3725aaee20fb5d706f53f85bade/src/server/WFHttpServer.h#L54

2、process结束不是回复的时机。关于回复的时机,我应该在文档里有写。server task所在series里没有其它任务了才回复。如果你不向series里加入任务,那也等价于process结束就回复。例子里,我们向series里放入一个http抓取任务。

3、proxy task就是一块内存而已,和线程没有关系。没有线程被挂起的。全程都是无堵塞的。

4、回复被触发的原因是,series里没有其它任务了,但series里有个last task,就是server task自己(server task不是所有series的首任务,而是最后一个任务)。server task被执行,而行为就是reply。

5、没有必要把任务和线程联系在一起,任务只是一块内存。至于都切换了几次线程,你可以自己打一下thread id。

HT-Sun commented 2 months ago

我现在明白了task仅仅作为一块内存,可以作为桥梁将不同的回调函数串联起来,task本身并不会执行具体的代码。但是我仍旧存在两个疑问:

  1. 第一个疑问实际上是好奇。我理解workflow作为一个框架,将一些细节屏蔽,可以让开发者专注自己的业务,这真的很棒。我好奇的点在于:在tut05中,当process执行完毕以后,到http_callback被调起的这段时间,workflow是如何完成了从proxy serve向web server发送请求的操作,是如何封装的,完全感知不到。在tut05提供的代码中,没有上述过程。我在阅读源码的过程中也没有找到对应的入口。

  2. 如何打印线程id。我仅在IOSession中找到了线程id,但似乎并不是我需要的。workflow有查询线程id的方法吗。

Barenboim commented 2 months ago

我现在明白了task仅仅作为一块内存,可以作为桥梁将不同的回调函数串联起来,task本身并不会执行具体的代码。但是我仍旧存在两个疑问:

  1. 第一个疑问实际上是好奇。我理解workflow作为一个框架,将一些细节屏蔽,可以让开发者专注自己的业务,这真的很棒。我好奇的点在于:在tut05中,当process执行完毕以后,到http_callback被调起的这段时间,workflow是如何完成了从proxy serve向web server发送请求的操作,是如何封装的,完全感知不到。在tut05提供的代码中,没有上述过程。我在阅读源码的过程中也没有找到对应的入口。
  2. 如何打印线程id。我仅在IOSession中找到了线程id,但似乎并不是我需要的。workflow有查询线程id的方法吗。

向webserver发送请求的操作,你先看一看第一个例子就知道了。proxy就是把http server和client结合起来,主要展示服务器如何等待一个异步请求而不阻塞线程。

获取当前线程id用pthread_self()调用就可以了。