进程&线程&协程
一个程序至少有一个进程,一个进程至少有一个线程。一个线程可以有唯一一个事件循环,一个事件循环可以创建多个协程。注意:协程是用户态的线程,线程是内核态的线程。
apisix~按域名进行请求转发
路由route路由(Route)是请求的入口点,它定义了客户端请求与服务之间的匹配规则。路由可以与服务(Service)、上游(Upstream)关联,一个服务可对应一组路由,一个路由可以对应一个上游对象(一组后端服务节点),因此,每个匹配到路由的请求将被网关代理到路由绑定的上游服务中。
如果前端调用后端接口时,前缀都是/kpi/index时,那apisix就不知道应该选择哪个路由了,这时,我们需要为路由添加域名,,这个域名就是requestheader中的host,即前端调用apisix-gateway时的域名,这个域名是需要解析到apisix-gateway的。
上游upstream上游列表包含了已创建的上游服务(即后端服务),可以对上游服务的多个目标节点进行负载均衡和健康检查。
上游中指定了你要转发到的后端服务,可以是具体的节点IP+端口,也可以通过服务发现来指定,如kubernetes,nacos,dns等
路由中按域名转发的必要性首先,这里的域名是指gateway的域名,一般是前端网站有个域名,然后它在调用后端服务时,会使用apisix-gateway ...
python异步连接redis
异步编程用官方模块asyncio实现注意导入的库是redis.asyncio。需要在连接、设置、获取等使用redis的地方可等待。
123456789101112131415161718192021import asyncio async def async_singal(): from redis.asyncio import StrictRedis ip = "172.17.0.8" redis_conn = await StrictRedis( host=ip, port=6379, encoding="utf8", decode_responses=True, db=0, ) await redis_conn.set("name", "async singal") res = await redis_conn.get("name") print(res)asy ...
StopIteration 异常标志着协程的结束
在 asyncio 事件循环中,StopIteration 异常并不直接参与协程的调度。相反,其他机制和异常在协程调度和任务管理中起到了关键作用。
协程的停止和StopIteration
当协程通过 await 表达式暂停时,它会生成一个等待的对象(通常是 Future 对象)。在协程执行完成后,它会通过引发 StopIteration异常来返回其结果。这与普通的生成器类似,当生成器完成时也会引发 StopIteration。
在 asyncio 中,当一个任务(Task)运行一个协程时,如果遇到 StopIteration异常,这表示协程已经完成执行,任务将从事件循环中移除,并将结果存储在任务对象中 (Stack Overflow)。
其他异常的处理
asyncio 事件循环在处理协程时会捕获并处理其他类型的异常。当协程在 await 表达式或其他代码中引发异常时,这些异常会被传播回到调用者,或传递给asyncio 的异常处理机制 (Stack Overflow)。
调度机制
当协程遇到 await表达式时,它会暂停执行,并将控制权返回给事件循环。事件循环会管理这些暂停的任务,等 ...
io多路复用与python协程asyncio的关系
IO多路复用(I/O Multiplexing)和Python的协程库asyncio有着密切的关系,因为它们都是用来处理并发操作的,但方式和层次有所不同。
IO多路复用IO多路复用是一种操作系统的功能,允许一个程序通过一个单独的线程来同时监视多个文件描述符(如网络连接、文件、管道等)的IO事件(如读、写、异常等)。常见的IO多路复用机制包括:
select()
poll()
epoll()(Linux特有)
kqueue()(BSD和macOS特有)
通过IO多路复用,程序可以在不使用多线程或多进程的情况下,高效地处理大量IO操作。这在网络服务器或客户端程序中非常常见。
Python的asyncioasyncio是Python中的一个库,提供了对异步IO、事件循环、协程(coroutines)和任务(tasks)的支持。asyncio使用了IO多路复用机制来实现高效的异步IO操作。
关系和实现在asyncio中,事件循环(Event Loop)是核心组件。它负责管理和调度协程,并使用IO多路复用来等待IO事件。常见的实现是通过select模块(在Unix和Windows上 ...
通过一个例子更好的理解协程-python
程序12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758import asyncioimport timeasync def async_io(idx: int): if idx == 1: await asyncio.sleep(1) else: await asyncio.sleep(6 - idx) print("async_io", idx) return idxasync def async_test1(): start = time.time() task1 = asyncio.create_task(async_io(1)) task2 = asyncio.create_task(async_io(2)) task3 = asyncio.create_task(async_io(3)) task4 = async ...
Golang 之协程详解
Golang 线程和协程的区别备注:需要区分进程、线程(内核级线程)、协程(用户级线程)三个概念。
进程、线程 和 协程 之间概念的区别
对于 进程、线程,都是有内核进行调度,有 CPU 时间片的概念,进行 抢占式调度(有多种调度算法)
对于 协程(用户级线程),这是对内核透明的,也就是系统并不知道有协程的存在,是完全由用户自己的程序进行调度的,因为是由用户程序自己控制,那么就很难像抢占式调度那样做到强制的CPU 控制权切换到其他进程/线程,通常只能进行 协作式调度,需要协程自己主动把控制权转让出去之后,其他协程才能被执行到。
goroutine 和协程区别
本质上,goroutine 就是协程。 不同的是,Golang 在 runtime、系统调用等多方面对 goroutine 调度进行了封装和处理,当遇到长时间执行或者进行系统调用时,会主动把当前goroutine 的CPU (P) 转让出去,让其他 goroutine 能被调度并执行,也就是 Golang 从语言层面支持了协程。Golang的一大特色就是从语言层面原生支持协程,在函数或者方法前面加 go关键字就可 ...
协程切换的三种底层实现方式
1.setjmp/longjmpsetjmp 和 longjmp 是C语言中用于实现基本的协程的底层函数。它们允许在一个函数的执行过程中保存当前的执行状态(包括寄存器和栈信息),然后在之后的某个时间点恢复到这个状态,从而实现函数的非局部跳转。这两个函数通常用于实现基于栈的协程,但它们相对较底层,因此需要小心使用,以避免引入潜在的错误。
setjmp 函数用于保存当前执行状态,并将其存储在一个 jmp_buf 结构中。jmp_buf 可以看作是一个保存了程序执行状态的数据结构。
longjmp 函数用于从一个 jmp_buf 中恢复保存的执行状态,将程序跳转到之前保存的状态。这通常用于协程的切换,允许程序在不同的执行状态之间切换,实现协程的挂起和恢复。以下是一个简单示例,演示了如何使用 setjmp 和 longjmp实现一个简单的协程:
1234567891011121314151617181920#include <stdio.h>#include <setjmp.h>#include <unistd.h>jmp_buf buf;vo ...
从栈切换的角度理解进程和协程
函数在执行时,会在栈上创建栈帧,并将执行的上下文保存在栈帧中。栈切换在计算机系统设计中发挥着重要作用,特别是在并发程序中。多进程或多线程程序可以并发执行,充分利用多CPU 多核的计算资源,从而显著提升应用程序性能。理解进程和线程的切换过程对于优化并发程序至关重要。
操作系统为了避免频繁进入内核态,会将许多工作尽量放在用户态中进行。深入理解内核态和用户态的含义及其影响,有助于评估操作系统进入内核态的开销。实现这些切换的关键在于对执行单元的上下文环境进行切换,而这正是由栈这一核心数据结构支撑的。
掌握协程的基本知识有助于在使用各种协程库时理解其内部机制,进而编写出正确的 IO程序。同时,深入理解操作系统的用户态和内核态转换,对于架构设计中正确评估操作系统的性能开销也至关重要。在讨论执行单元的切换与栈的关系之前,需要给出它的准确定义。
什么是执行单元执行单元是指 CPU 调度和分派的基本单位,它是一个 CPU 能正常运行的基本单元。执行单元是可以停下来的,只要能把 CPU状态(其实就是寄存器的值)全部保存起来,等到这个执行单元再被调度的时候,就把状态恢复过来就行了。我们把这种保存状态,挂起, ...
python 协程详解
Python中的协程经历了很长的一段发展历程。其大概经历了如下三个阶段
最初的生成器变形yield/send
引入@asyncio.coroutine和yield from
在最近的Python3.5版本中引入async/await关键字
协程是什么协程,又称微线程,纤程。英文名Coroutine,是一种用户态的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此:协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,就相当于进入上一次调用的状态,换种说法:进入上一次离开时所处逻辑流的位置。
寄存器上下文和栈保存到其他地方
线程和进程的上下文切换是由内核管理的。协程则是在用户态下运行,它不依赖于内核的调度,而是由用户程序自行管理。因此,协程的上下文保存和恢复通常是由程序库(如 Python 的 asyncio 或 Go 的 goroutine 库)来处理的。
具体来说,协程的上下文和栈保存位置可以是
程序的堆内存:协程上下文和栈信息通常会保存在程序的堆内存中。每个 ...