程序员

Dragonwell特性: Wisp

作者:admin 2021-06-07 我要评论

1、协程与异步编程? 1、多线程和事件模型? 在Web Server领域 最早像Apache?Server 大家都是使用多线程模型处理并发。下图左边这张图是通过多个进程去处理多个用...

在说正事之前,我要推荐一个福利:你还在原价购买阿里云、腾讯云、华为云服务器吗?那太亏啦!来这里,新购、升级、续费都打折,能够为您省60%的钱呢!2核4G企业级云服务器低至69元/年,点击进去看看吧>>>)

1、协程与异步编程?

1、多线程和事件模型?

在Web Server领域 最早像Apache?Server 大家都是使用多线程模型处理并发。下图左边这张图是通过多个进程去处理多个用户不同的请求 可能在一个单核系统上也可以去创建多个进程来处理这些请求 但这实际上操作系统给大家一个假象 操作系统通过分时互动机制去不停的切换线程 表现出一种正在同时执行的假象。?

image.png?

实际上这个切换是非常消耗资源的 然后我们看右边这张图NGINX 他率先使用了事件模型 让大家科学认知到在单个线程里通过业务代码去切换不同的上下文 这样可以大大减少操作系统里面限制切换开销 很好的提高性能。?

?

2、上下文切换?

上下文切换会吃掉宝贵的CPU资源 大家很多情况下对上下文有误区 进出内核和调度之间其实很大差异的。假如像刚才这种场景 我们看到多个线程来回调用 那一个线程当它资源耗尽或者比较阻塞的时候 下个线程选谁 其实操作系统需要进行调度 真正的损耗远大于想象。?

image.png?

我们可以看到进出内核是上图左边灰色这一列 它的耗时是很小的 可能在几十到一百纳秒级别。然后假如这一次系统调用它触发了切换 比如读一个程序里面有数据 信令要挂起会触发上下文切换 如果希望有调度 开销就会很大 会达到40倍左右。?

?

3、使用异步编程?

所以如果在编程中引发调度的切换开销是很大的 我们应该尽量避免。怎么避免呢 答案就是异步编程 在node.js里面 我们可以使用大量callback区域处理业务逻辑。当使用callback以后 代码可能会变成这样一种三角形 因为每一个组织方式 它后面返回值都要带callback调用 都会缩进去一层。这样业务逻辑非常难以维护。?

其次是即便我使用了异步编程 但可能还是不小心在现实里面使用了一段阻塞代码 下图是NGINX官网所提供的图片 虽然我自己去切换不同的请求处理 但是中间可能还是不小心调用了操作系统的一个阻塞方法。?

image.png?

为了解决这个问题 NGINX虽然是一个号称纯异步事件驱动的模型 但是它最近也引入了线程池去处理这种可能阻塞现实的情况。?

?

4、引入协程?

其实最早在操作系统里没有协程的概念 大家都是通过协程做逻辑上抽象来帮助我们写并发代码。?

image.png???image.png?

比如说这里有两段code 一段是解压的code 一段是?parser的code。大家要从解压数据结构里面去解析数据 这里对数据进行简单的encode 如果char是普通字符 会直接返回。若是特殊字符 可能就进行一个长度encode。用协程来组织逻辑 emit() 和 parser::getchar()会切换到另一个协程 如果没有协程需要两个线程结合pipe来组织 但如果有协程 我们可以在?frame里面直接控制 逻辑清晰且性能高。?

我们看怎么实现协程。协程的执行上下文其实包括这几个部分 当前的站、局部变量、当前代码位置 这些其实都可以通过数据表示。?

?image.png?

与OS内的线程切换方式一致?

(1) 保存pc?

(2) 保存sp?

(3) 保存callee-save寄存器?

保存完这些后 将来想回去 只要通过反向计算器pop出来 就会回到之前上下文。协程场景下 emit和?getchar都是通过这种方式去实现的。?

?

5、现代编程语言中的协程?

image.png?

左边是VERT.X ?Java里面最近比较流行的框架 想要制作的就是Java里的node.js的生态 我们可以看到官方所提供的连接数据库例子。?

Client.getConnection 来获取数据库连接 但它不是说立马返回一个连接给到我们 而是提供callback 然后这个result里面表示执行是否成功 如果成功的话 我们可以通过result去拿到?connection。这就是通过义务编程的方式 去让我们在线程里面处理大的逻辑 NGINX就是这样的一种方式。这样代码其实看起来是非常难以维护的 比如在里面需要通过result set去把数据放到缓存里面 又是一个远程调用需要阻塞 可能又是一种callback 这个嵌套会非常深 非常难处理 由于我们都是callback 所以这个站就没法被维持 假如在这个地方有异常就非常难以处理。?

现代编程语言是怎么解决这个问题 我们给的答案是协程。ES7、C#?他们都提供协程来帮助解决这类问题。我们以一段Kotlin代码为例 看协程怎么帮助代码改写成非常直观的代码,Kotlin里面通过suspend关键字来表示 函数是可以被挂起的 然后它也可以在?client上新加的方法 新的方法叫Agetconnection。里面调用Kotlin提供的非常?medical的方法 他会获取一个当前执行上下文的connection 让我们getConnection直接调用。getConnection的callback是恢复当前协程的执行 并且把拿到connection作为返回值。这样实际上不用一直占着?CPU资源 实际上调度器会继续去调度其他执行 一旦进行这类封装以后 我们看到代码可以被简化为下面这种形式。?

image.png?

Conn clinet.?AGetConnection ?

然后?rs ?Conn?.aQurerythat(“SELECT * FROM ...”)?

这段代码相比左边这段代码那就是大大简化了 但我们要做对这种回调形式进行封装。?

6、Dragonwell: Wisp 原理?

image.png?

既然要对这么多回调形式进行封装 工作量是非常大的 能不能在更底层去解决 为什么就提供了这一层帮助 因为jdk提供所有的阻塞方式都是在jdk里面提供的。比如说Java.lang.Thread、j.u.c、java.io、synchronized这些都是有可能阻塞API。在这些API上我们都做了封装 ?Wisp把这些脏活苦活全部给做掉了.?Wisp还对现成模型进行一个映射。我们知道Java里面的Java thread和操作系统pthread是1:1的映射关系 大量线程使用的话就会导致前面提到的上下切换问题。但是在Wisp下我们每一个线程都被映射到一个Wisp wisp执行过程中可能阻塞CPU 然后这时候就可以让pthread调动其他Wisp 调度效率非常高 可以免费提高应用的性能。?

?

二、使用Wisp提升微服务性能?

Dragonwell: Wisp demo?

下面在Dragonwell下用 使用Wisp提高性能的例子?

image.png?image.png?

左边这张图是不开Wisp 使用wrk压测工具去压这台机器 192.168.1.101 8080端口 平均的延迟是522微秒 QBS是不到5万 在同个应用完全不改代码情况下 我们调整一下界面参数把Wisp打开 然后线程就被完全意识到协程了 latency降低到270多微秒 ?QBS变成了6万多 大概有20%多的性能提升 这不需要修改任何应用代码 是一个免费的性能午餐 所以推荐大家可以通过Wisp提高我们微服务的性能表现。?


本文转自网络,原文链接:https://developer.aliyun.com/article/784538

版权声明:本文转载自网络,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。本站转载出于传播更多优秀技术知识之目的,如有侵权请联系QQ/微信:153890879删除

相关文章
  • 第 2 章 基本数据类型

    第 2 章 基本数据类型

  • LeetCode笔记:Weekly Contest 234 比

    LeetCode笔记:Weekly Contest 234 比

  • 2021-04-11

    2021-04-11

  • 字符串算法 |   AC自动机算法

    字符串算法 | AC自动机算法

腾讯云代理商
海外云服务器