当前位置: 首页 > news >正文

网站标题应怎设置微信网站开发框架

网站标题应怎设置,微信网站开发框架,iis wordpress安装教程,深圳网站建设招聘为了解决多线程服务器在高并发的I/O密集型应用中的不足#xff0c;同时避免早期简单单线程服务器的性能障碍#xff0c;Node.js采用了基于事件循环的非阻塞式单线程模型#xff0c;实现了如下两个目标#xff1a; #xff08;1#xff09;保证每个请求都可以…为了解决多线程服务器在高并发的I/O密集型应用中的不足同时避免早期简单单线程服务器的性能障碍Node.js采用了基于事件循环的非阻塞式单线程模型实现了如下两个目标 1保证每个请求都可以快速响应 2实现远超过多线程模型的并发连接数。 提示Node.js在JS层面是单线程的——没有创建新线程的机制。但是在底层的C/C层面是多线程的即访问底层操作系统服务时存在多个并发工作线程的情形——使用了线程池。 阻塞执行 阻塞Block也称为同步执行Synchronize只有前面的操作全部执行完成才能开始后续操作。常规的多线程服务器内部都是采用的是阻塞执行 var connmysql.createConnection(...); //步骤1 var resultconn,query(INSERT...); //步骤2 conn.end(); //步骤3 非阻塞执行 非阻塞Non—block也称为异步执行Asynchronize后面的操作不必等待之前操作的执行完毕可以先执行。 const fsrequire(fs); console.log(读取请求数据); //操作1 fs.writeFile(app.log,访问日志,(){ //操作2console.log(写出操作日志); }) console.log(输出响应数据); //操作3 //读取请求数据 //输出响应数据 //写出操作日志 异步回调 Node.js中的业务代码都是在单一的主线程中执行的当遇到耗时的阻塞操作时如文件IO、网络访问、数据库请求等不会等待其执行完毕而是注册一个处理函数执行结果的回调函数继续执行后续的代码。 待耗时的阻塞操作执行完成时其对应的回调函数会转入回调函数队列主线程在下次事件循环时会执行这些回调函数。 同步函数调用 const fsrequire(fs); var datafs.readFileSync(app.log); console.log(文件内容,data); console.log(程序执行完成); //文件内容121212 //程序执行完成 异步函数调用 const fsrequire(fs); fs.readFile(app.log,function(err,data){console.log(文件内容,data) }) console.log(程序执行完成); //程序执行完成 //文件内容121212 事件驱动 事件驱动编程是一种以事件为基础的编程范式其中程序的执行是由事件的发生和相应的事件处理程序来驱动的。让我们详细了解事件循环和异步编程并结合示例说明。 事件循环 事件循环是事件驱动编程的核心机制之一它负责监听和分发事件并调用相应的事件处理程序来响应事件。事件循环在一个持续运行的循环中不断地从事件队列中获取事件并按照事件的顺序依次处理。常见的事件循环模型是基于单线程的每次只处理一个事件避免了并发访问的问题。 示例 const eventEmitter require(events);// 创建事件发射器 const emitter new eventEmitter();// 监听事件 emitter.on(event, (data) {console.log(Event received:, data); });// 触发事件 emitter.emit(event, Hello, world!); 在这个示例中我们创建了一个事件发射器并使用on方法来监听一个名为event的事件。当event事件被触发时事件处理程序会被调用并将事件数据传递给它。最后我们使用emit方法触发了event事件并传递了数据Hello, world!。这样事件处理程序会被调用并输出Event received: Hello, world!。 异步编程 异步编程是事件驱动编程中的重要概念它允许程序在执行耗时操作时不阻塞主线程而是通过回调函数、Promise、async/await等机制来处理操作的结果。这样可以提高程序的并发性能避免了长时间的等待。 libuv 利用编译好的libuv库文件我们可以开始写一个简单又经典的例子 Hello world。 #include stdio.h #include uv.hint main() {uv_loop_t *loop uv_default_loop();printf(hello libuv);uv_run(loop, UV_RUN_DEFAULT); } event-loop线程 我们都知道线程是操作系统最基本的调度单元而进程是操作系统的最基本的资源分配单元因此可以知道进程其实是不能运行能运行的是进程中的线程。进程仅仅是一个容器包含了线程运行中所需要的数据结构等信息。一个进程创建时操作系统会创建一个线程这就是主线程而其他的从线程都要在主线程的代码来创建也就是由程序员来创建。因此每一个可执行的运用程序都至少有一个线程 于是libuv一开始便启动了event-loop线程再在这个主线程上利用线程池去创建更多的线程。在event-loop线程中是一段while(1)的死循环代码直到没有活跃的句柄的时候才会退出这个时候libuv进程才被销毁掉。清楚这点对于后面的学习至关重要。 Handle 中文翻译为句柄如[译文]libuv设计思想概述一文所属整个libuv的实现都是基于Handle和Request。所以理解句柄以及libuv提供的所有句柄实例才能够真的掌握libuv。按照原文所述句柄是 表示能够在活动时执行某些操作的长生命周期对象。 理解这句话的意思,首先我们抓住两个关键词长生命周期、对象。Libuv所有的句柄都需要初始化而初始化都会调用类似这种函数uv_xxx_init。xxx表示句柄的类型在该函数中会将传入的形参handle初始化并赋值返回具体的对象比如初始化tcp句柄 ... // 随便截取一段初始化代码 handle-tcp.serv.accept_reqs NULL; handle-tcp.serv.pending_accepts NULL; handle-socket INVALID_SOCKET; handle-reqs_pending 0; handle-tcp.serv.func_acceptex NULL; handle-tcp.conn.func_connectex NULL; handle-tcp.serv.processed_accepts 0; handle-delayed_error 0 ... 理解了句柄其实就是个对象那么长生命周期要是怎样的还是以TCP句柄为例子你在这个例子tcpserver.c中可以看到后面tcp服务器的操作绑定端口、监听端口都是基于tcp句柄整个句柄存活于整个应用程序只要tcp服务器没有挂掉就一直在因此说是长生命周期的对象。 libuv提供的所有句柄如下 接下去我们简单介绍以下所有的Libuv的句柄 uv_handle_t 首先libuv有一个基本的handle, uv_handle_tlibuv是所有其他handle的基本范式任何handle都可以强转为该类型并且和该Handle相关的所有API都可以为其他handle使用。 libuv能否一直运行下去的前提是检查是否有活跃的句柄存在而检查一个句柄是否活跃(可以使用方法uv_is_active(const uv_handle_t* handle)检查)根据句柄类型不同其含义也不一样 uv_async_t句柄总是活跃的并且不能停用除非使用uv_close关闭掉uv_pipe_t、uv_tcp_t, uv_udp_t等这些牵扯到I/O的句柄一般也都是活跃uv_check_t, uv_idle_t, uv_timer_t等当这些句柄开始调用uv_check_start(), uv_idle_start()的时候也是活跃的。 而检查哪些句柄活跃则可以使用这个方法uv_print_active_handles(handle-loop, stderr); 以tcpserver.c为例子我们启动tcp服务器后启动一个定时器去打印存在的句柄结果如下 [-AI] async 0x10f78e9d8 [RA-] tcp 0x10f78e660 [RA-] timer 0x7ffee049d7c0 可以看到tcp的例子中一直存活的句柄是async、tcp、timer。它们前面中括号的标志解释如下 R 表示该句柄被引用着 A 表示该句柄此时处于活跃状态 I 表示该句柄是内部使用的 uv_timer_t 顾名思义Libuv的计时器用来在将来某个时候调用对应设置的回调函数。其调用时机是在整个轮询的最最开始后面我们会说到轮询的整个步骤。 uv_idle_t Idle句柄在每次循环迭代中运行一次给定的回调而且执行顺序是在prepare句柄之前。 与prepare句柄的显著区别在于当存在活动的空闲句柄时循环将执行零超时轮询而不是阻塞I/O。 在uv_backend_timeout方法中我们可以看到返回的轮询I/O超时时间是0 if (!QUEUE_EMPTY(loop-idle_handles))return 0; idle句柄的回调一般用来执行一些低优先级的任务。 **注意尽管名称叫做“idle”空闲句柄在每次循环迭代时都会调用它们的回调函数 而不是在循环实际上是“空闲”的时候。** uv_prepare_t  prepare句柄将在每次循环迭代中运行一次给定的回调而且是选择在I/O轮询之前。 问题是libuv为什么要创造这么一种句柄其实从名称来猜测libuv应该是想提供一种方式让你可以在轮询I/O之前做些事情然后在轮询I/O之后使用check句柄进行一些结果的校验。 uv_check_t check句柄将在每次循环迭代中运行一次给定的回调而且是选择在I/O轮询之后。其目的在上面已经提过 uv_async_t Async句柄允许用户“唤醒”事件循环并在主线程(原文翻译为another thread其实不对)调用一开始注册的回调。这里说的唤醒其实就是发送消息给主线程(event-loop线程)让其可以执行一开始注册的回调了。 **注意libuv会对uv_async_send()做一个聚合处理。 也就是说它并不会调用一次就执行一次回调。** 我们使用thread.c为例子使用uv_queue_work和uv_async_send来实践得到的结果打印如下 // 打印出主进程ID号和event-loop线程ID I am the master process, processId 90714 I am event loop thread 0x7fff8c2d9380// 这个是uv_queue_work执行的回调 从线程ID可以看到回调函数是在线程池中的某个线程中执行 I am work callback, calling in some thread in thread pool, pid90714 work_cb thread id 0x700001266000// 这个是uv_queue_work执行完回调后结束的回调 从线程ID可以看到这个回调已经回到了主线程中执行 I am after work callback, calling from event loop thread, pid90714 after_work_cb thread id 0x7fff8c2d9380// 这个是uv_async_init的回调其触发是因为在work callback中执行了uv_async_send 可以从0x700001266000得到验证该回调也是在主线程中执行 I am async callback, calling from event loop thread, pid90714 async_cb thread id 0x7fff8c2d9380 I am receiving msg: This msg from another thread: 0x700001266000 uv_poll_t Poll句柄用于监视文件描述符的可读性、可写性和断开连接类似于poll(2)的目的。 Poll句柄的目的是支持集成外部库这些库依赖于事件循环来通知套接字状态的更改比如c-ares或libssh2。不建议将uv_poll_t用于任何其他目的;因为像uv_tcp_t、uv_udp_t等提供了一个比uv_poll_t更快、更可伸缩的实现尤其是在Windows上。 可能轮询处理偶尔会发出信号表明文件描述符是可读或可写的即使它不是。因此当用户试图从fd读取或写入时应该总是准备再次处理EAGAIN错误或类似的EAGAIN错误。 同一个套接字不能有多个活跃的Poll句柄因为这可能会导致libuv出现busyloop或其他故障。 当活跃的Poll句柄轮询文件描述符时用户不应关闭该文件描述符。否则可能导致句柄报告错误但也可能开始轮询另一个套接字。但是可以在调用uv_poll_stop()或uv_close()之后立即安全地关闭fd。 下面罗列的是轮询的事件类型 enum uv_poll_event {UV_READABLE 1,UV_WRITABLE 2,UV_DISCONNECT 4,UV_PRIORITIZED 8 }; uv_signal_t Signal句柄在每个事件循环的基础上实现Unix风格的信号处理。在udpserver.c中展示了Signal句柄的使用方式 uv_signal_t signal_handle; r uv_signal_init(loop, signal_handle); CHECK(r, uv_signal_init);r uv_signal_start(signal_handle, signal_cb, SIGINT);void signal_cb(uv_signal_t *handle, int signum) {printf(signal_cb: recvd CTRLC shutting down\n);uv_stop(uv_default_loop()); //stops the event loop } 关于Signal句柄有几个点要知悉 以编程方式调用raise()或abort()触发的信号不会被libuv检测到;所以这些信号不会对应的回调函数。SIGKILL和SIGSTOP是不可能被捕捉到的通过libuv处理SIGBUS、SIGFPE、SIGILL或SIGSEGV会导致未定义的行为 uv_process_t process句柄将会新建一个新的进程并且能够允许用户控制该进程并使用流去建立通信通道。对应的demo可以查看process.c值得注意的是args中提供的结构体的第一个参数path指的是可执行程序的路径比如在demo中 const char* exepath exepath_for_process(); char *args[3] { (char*) exepath, NULL, NULL }; 实例中的exepath是FsHandle的执行路径。 另外一个注意点就是父子进程的std的配置demo中提供了一些参考如果使用管道的话还可以参考另外一个demopipe uv_stream_t 流句柄提供了双工通信通道的抽象。uv_stream_t是一种抽象类型libuv以uv_tcp_t、uv_pipe_t和uv_tty_t的形式提供了3种流实现。这个没有具体实例。但是libuv有好几个方法的入参都是uv_stream_t说明这些方法都是可以被tcp/pipe/tty使用具体有 int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) int uv_accept(uv_stream_t* server, uv_stream_t* client) int uv_read_start(uv_stream_t* stream, uv_alloc_cb alloc_cb, uv_read_cb read_cb) int uv_read_stop(uv_stream_t*) int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb) int uv_write2(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbu uv_tcp_t tcp句柄可以用来表示TCP流和服务器。上小节说到的uv_stream_t是uv_tcp_t的”父类“这里使用结构体继承的方式实现uv_handle_t、uv_stream_t、uv_tcp_t三者的结构关系如下图 使用libuv创建tcp服务器的步骤可以归纳为 1、初始化uv_tcp_t: uv_tcp_init(loop, tcp_server) 2、绑定地址uv_tcp_bind 3、监听连接uv_listen 4、每当有一个连接进来之后调用uv_listen的回调回调里要做如下事情4.1、初始化客户端的tcp句柄uv_tcp_init()4.2、接收该客户端的连接uv_accept()4.3、开始读取客户端请求的数据uv_read_start()4.4、读取结束之后做对应操作如果需要响应客户端数据调用uv_write回写数据即可。 uv_pipe_t Pipe句柄在Unix上提供了对本地域套接字的抽象在Windows上提供了命名管道。它是uv_stream_t的“子类”。管道的用途很多可以用来读写文件还可以用来做线程间的通信。我们在实例中用来实现主线程与多个子线程的互相通信。实现的模型是这样的 uv_udp_t UDP句柄为客户端和服务器封装UDP通信。使用libuv创建udp服务器的步骤可以概括为 1、初始化接收端的uv_udp_t: uv_udp_init(loop, receive_socket_handle) 2、绑定地址uv_udp_bind 3、开始接收消息uv_udp_recv_start 4、uv_udp_recv_start里执行回调可以使用下面方法回写数据发送给客户端4.1、uv_udp_init初始化send_socket_handle4.2、uv_udp_bind绑定发送者的地址地址可以从recv获取4.3、uv_udp_send发送指定消息 uv_fs_event_t FS事件句柄允许用户监视一个给定的路径的更新事件例如如果文件被重命名或其中有一个通用更改。这个句柄使用每个平台上最佳的解决方案。 uv_fs_poll_t FS轮询句柄允许用户监视给定的更改路径。与uv_fs_event_t不同fs poll句柄使用stat检测文件何时发生了更改这样它们就可以在不支持fs事件句柄的文件系统上工作。 Request 那么接下去就说到Request这个短生命周期的概念中文翻译为”请求“类似于nodejs中的req,它也是一个结构体。还是以上述的tcp服务器为例子有这么一段代码 if (r 0) {// 如果接受连接失败需要清理一些东西uv_shutdown_t *shutdown_req malloc(sizeof(uv_shutdown_t));r uv_shutdown(shutdown_req, (uv_stream_t *)tcp_client_handle, shutdown_cb);CHECK(r, uv_shutdown);} 当客户端连接失败需要关闭掉这个连接于是我们就会初始化一个request然后传递给我们需要请求的操作这里是关闭请求shutdown。 uv_request_t是基本的request其他任何request都是基于该结构进行扩展它定义的所有api其他request都可以使用。和uv_handle_t一样的功效。 libuv运行的三种模式 接着说说Libuv提供的三种运行模式 UV_RUN_DEFAULT 默认轮询模式此模式会一直运行事件循环直到没有活跃句柄、引用句柄、和请求句柄UV_RUN_ONCE 一次轮询模式此模式如果pending_queue中有回调则会执行回调而直接跨过uv__io_poll。如果没有则此方式只会执行一次I/O轮询uv__io_poll。如果在执行过后有回调压入到了pending_queue中则uv_run会返回非0你需要在未来的某个时间再次触发一次uv_run来清空pending_queue。UV_RUN_NOWAIT 一次轮询无视pending_queue模式此模式类似UV_RUN_ONCE但是不会判断pending_queue是否存在回调直接进行一次I/O轮询。
http://www.sadfv.cn/news/145539/

相关文章:

  • 网站建设的主要流程步骤谷歌下载
  • 深圳微信网站运营检查色盲效果网站
  • 织梦网站手机版怎么做长沙高新区住房和建设管理局网站
  • 重庆制作网站首页做一年的网站能赚多少钱
  • 扬州市建设局网站 竣工备案怎样写网站设计意义
  • 静态摄影网站模板wordpress4.6.1中文版
  • 潍坊 公司 网站算卦网站开发
  • 一条龙网站建设价格贵阳app开发定制
  • 网站地址栏图标文字wordpress可以干什么
  • 上海市建设工程招标造价网站做网站保定
  • 网站托管做的好的公司wordpress 图集
  • 个人博客网站备案吗wordpress文章保存目录
  • 做网站购买域名之后成都市建设招标网站
  • 网站如何绑定域名免费建设个人手机网站
  • 国外网站html5从上到下连续变动优盖网logo在线设计
  • 辽宁奔之流建设工程有限公司网站com域名类别
  • 网站子目录怎么做反向代理设置微信公众平台登录入口内村完小
  • 网站开发流程怎么写给手机做网站的公司
  • 如何使用wordpress制作网站门户网站建设的企业
  • 网站后台建设教程下载营销成功案例分享及感悟
  • 网站开发需要注册账户吗智联招聘网站多少钱做的
  • 笔记本电脑做网站比较畅快做网站要开发嘛
  • 网站首页模板设计图深圳小程序搭建
  • 邯郸建立网站费用ps制作网站导航图片
  • 小猫济南网站建设公司合肥关键词排名首页
  • 网站制作代码大全上海网站建设价钱
  • 电商网站的建设的主要目的龙岗平湖网站建设公司
  • 网站开发使用软件有哪些永川网站制作
  • 用6数字域名做网站的是网业翻译成中文
  • 网站前期设计企业信息查询单在哪里打印