聊聊工作中經常遇到的「異步」

2020-09-05 Hu先生Linux後臺開發

在我們編程的時候,經常會遇到一個概念——異步,諸如異步通信,異步線程,異步代碼,異步調用,異步編程等等,那麼

什麼是異步呢?

為什麼要異步?

異步的典型場景是什麼?

如何使用異步呢?

......

異步——通信?

老碼農初識異步是從單片機的串行通信開始的。串行通信,是指通信雙方按位進行,遵守時序的一種通信方式。串行通信有兩種類型,一種是同步通信,另一種就是異步通信。

同步通信的特點是要求發送時鐘和接收時鐘保持嚴格的同步,異步通信的發送端和接收端可以由各自的時鐘來控制數據的發送和接收,這兩個時鐘源彼此獨立,互不同步。異步通信中的接收方並不知道數據什麼時候會到達,發送方發送的時間間隔可以不均勻,接收方是在數據的起始位和停止位的幫助下實現信息同步的。簡單的說,異步是扔出去一段數據,對方靠著內容前後所檢查到的特殊性發現了它,把這個內容存下來;而同步通信是對方在時刻等著發送方發號施令,發送方告訴對方要發送了,然後雙方一拍即合。

從通信效率來看,同步通信效率高,異步通信效率較低。但從實現方式來看,同步通信較複雜,異步通信相對簡單,計算機的接口大多是異步的。

進一步,對通信網絡而言,同步網一般是指網絡內所有電信設備的時鐘(或載波)提供同步控制信號,使它們的頻率工作在共同速率(或頻率)上的支撐網。同步網可分為準同步網和同步網兩類,由具有相同標稱頻率的不同基準時鐘互相比對的同步網稱為準同步網,由單一基準時鐘控制的稱為同步網。我國和大多數國家採用分級主從同步法,國家間採用準同步法。異步網絡不需要時間同步,可以在任何節點完成逐分組的轉發,這種分組的不可預測和不規則機制增加了網絡的阻塞率。然而,異步網絡具有同步網絡所不具備的低成本、低複雜度、高健壯性和高靈活性,通過合理設計交換的結構和協議,也可達到良好的交換性能。

關於通信網乃至TMN,太容易給人帶來回憶了。跳出湧現的往事,對程式設計師而言,異步的概念有了相當程度的延伸。

視頻資料獲取後臺私信【架構】

異步——編程?

編程中的同步與異步往往是指兩個對象之間的調用關係:

  • 同步調用:調用者發出一個調用時,在沒有得到結果之前,該調用不返回。一旦調用返回,就得到返回值了,也就是由調用者主動等待這個調用的結果。
  • 異步調用:調用者發出一個調用之後,這個調用就直接返回了,沒有返回結果,也就是當一個異步調用發出後,調用者不會立刻得到結果。而是在調用發出之後,被調用者通過狀態、消息等來通知調用者,或通過回調函數處理這個調用。

對於異步編程而言,和軟體系統的架構設計有類似的地方,大體上,可以分為面向CPU的異步編程和面向IO的異步編程這兩種方式。

面向CPU 的異步

我們常見的多線程中就會經常遇到面向CPU的異步編程。線程是作業系統能夠進行運算調度的最小單位,它被包含在進程之中,是進程中的實際運作單位。同步線程是指兩個線程的運行是相關的,其中一個線程可能要阻塞等待另外一個線程的運行。異步線程是兩個線程毫不相關,自己運行自己的。

這裡也經常遇到另外的兩個概念——阻塞和非阻塞,在多線程編程中,主要是指線程是否需要等待。阻塞調用指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之後才會返回。非阻塞調用是指在不能立刻得到結果之前,該調用不會阻塞當前線程。

在Android上編程的時候,UI主線程和子線程的交互幾乎是不可或缺的。在伺服器側,同樣如此,SpringBoot 中配置異步線程池的簡單示例如下:


//啟動異步

@EnableAsync

//配置類

@Configuration

class ThreadsPoolConfig {


@Bean(&34;)

public Executor taskExecutor() {

//創建建線程池

ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

//初始的線程數量

executor.setCorePoolSize(INI_THREAD_NUM);

//最大的線程數量

executor.setMaxPoolSize(MAX_THREAD_NUM);

//隊列的最大容量

executor.setQueueCapacity(MAX_QUEUE_CAP);

//存活時間

executor.setKeepAliveSeconds(ALIVE_TIME);

//線程池的飽和策略

executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());

//關閉線程池時是否等待任務完成

executor.setWaitForTasksToCompleteOnShutdown(true);

//等待終止的時間

executor.setAwaitTerminationSeconds(WAIT_TERMINATE_TIME);


return executor;

}

}

面向IO的異步

面向IO的操作,是異步編程的應用場所之一。在通過IO訪問數據的方式,同步編程需要主動讀寫數據,在讀寫數據的過程中還是可能會遇到阻塞;異步編程只需要I/O操作完成的通知,並不主動讀寫數據,而是由作業系統內核完成數據的讀寫。

在《Unix網絡編程》第二卷中,提到了5種IO模型:

前四種io模型為同步io模型,只有異步io模型與posix定義的io相匹配。異步IO在用戶進程觸發I/O操作以後就立即返回,繼續開始做自己的事情,而當I/O操作已經完成的時候會得到I/O完成的通知。異步IO的執行者是內核線程,內核線程將數據從內核態拷貝到用戶態,所以沒有阻塞。

Linux2.6以後引入了AIO,主流的IO機制可能是EPOLL,一種性能卓越且編程簡單的異步IO機制,在Nginx的配置中就可以看到它的身影。

網絡編程中的異步

網絡編程是一種特殊的IO操作,socket 編程中同樣存在著同步和異步調用。網絡編程的目的是網絡通信,而網絡通信的傳輸協議無外乎那八字的四原則:

  • 組裝
  • 復用
  • 糾錯
  • 流控

在Python中,可以asyncio來實現網絡通信中的異步編程,asyncio庫包含異步IO、事件循環、協程、task等內容,事件循環是asyncio提供的核心運行機制。

從分布式系統的角度來看,消息隊列提供了異步通信的能力,藉助消息隊列,多個模塊間可以靈活的進行消息傳遞,這裡的異步通信就是指消息生產者可以將消息放入隊列中,而不等待結果返回,由消息隊列負責投遞消息給消費者。在系統設計中,我們可以通過消息隊列來進行模塊間的通信。

太多的概念了,其實都是為了試圖理解「異步」這一核心概念,還是舉個例子吧。

DuerOS 中的異步推送

DBP開放平臺向開發者開放了技能內異步推送的機制,技能內推送意味著開發者能夠在用戶的會話周期內,異步調用推送接口向設備端推送相關內容或協議指令。典型的應用場景,包括銀行類耗時較長的操作處理,對用戶的異步通知等等。

目前DBP平臺提供了兩大類的異步推送,分別為文本和BOT協議。文本又分為純文本,使用該類型將在設備端底部展示一個通知,同時內容為文本內容;另一種是TTS,設備端將用語音播報相關的TTS;BOT協議提供了更豐富的設備端內容展示的情景。

權限申請

使用服務之前需要先在DBP開放平臺申請該服務的權限:

編輯技能->配置服務,在服務權限配置下可以看到「技能內異步推送」,點「申請」,申請信息會加到審核列表裡,待運營人員審核通過後,服務的狀態將變成「已通過」,服務的權限即申請完成。若想下掉該權限,點擊「下線」即可下線服務。

使用模板

文本模板

依次點擊&34;,進入文本模板頁,該頁由DBP提供了部分通用的系統模板,開發者只需在調用相關接口時更改相關參數即可:

通配參數在模板裡用%%包含的字符串表示,同時該頁面提供了渲染模板的測試工具,填入相應的模板ID、參數的鍵值對,點擊生成後就能得到最終渲染完的文本內容:

BOT協議模板

點擊「BOT協議」導航,進入BOT協議模板列表頁,這裡列出了DBP當前支持使用的BOT協議模板:

如上圖,目前DBP提供了AudioPlayer.Play指令模板,使用該指令時,通過推送接口將會讓設備端調起AudioPlayer並播放指定的音頻。

點擊AudioPlayer.Play連結,進入詳情頁,詳情頁裡展示了該指令支持的欄位、欄位類型、可選、是否可自定義以及示例等信息,推送接口將會根據這些定義項進行數據校驗,開發者在使用時不要傳錯數據:

對於部分模板,DBP提供了可自定義的欄位,可以設置自定義欄位的鍵與類型,提交審核通過後,就可以使用了,目前支持的類型分別為STRING,INT, ARRAY, OBJECT, BOOLEAN,所填的欄位都是必須傳的,推送接口會校驗相應的欄位與類型:

DEBUG 調試

BOT協議模板未審核通過前,可以先debug,debug時需要用戶綁定自己的設備SN,設備SN在設備的底部,每個技能最多只能綁定5個設備:

調用推送接口

推送接口地址為:https://xiaodu.baidu.com/saiya/v1/notification/reprompt,method為POST,需要設置Content-Type為application/json:


$ curl --location --request POST &39; \

--header &39; \

--header &39; \

--data-raw &34;dialogRequestId&34;notificationType&34;plainText&34;templateId&34;1&34;debug&34;templateParams&34;userName&34;張三&34;botName&34;測試技能&39;


其中header裡要將{{apiAccessToken}}替換成實際的apiAccessToken,該值從BOT request裡獲取,在context.System.apiAccessToken裡。POST的body為json格式,其中:

  • dialogRequestId: 必選,從request裡獲取request.dialogRequestId
  • notificationType: 必選,值分別為,plainText-純文本類型,將在有屏設備底部以通知方式呈現;plainTts-將以語音方式播報;botProtocol-BOT協議類型
  • templateId: 必選,當notificationType為plainText和plainTts時,這個值就是內容模板裡的模板ID值,為數值;當為botProtocol時,就是BOT協議裡的指令名稱,如AudioPlayer.Play
  • debug: 可選,為1時,工作在debug模式,指令只能往指定設備推送,為0或不填時工作在線上模式
  • templateParams: 可選,當notificationType為plainText和plainTts時,內容為文本模板裡參數的鍵值對;當為botProtocol時,值為具體的BOT協議內容。

例如,一個bot協議的推送請求如下:

curl --location --request POST &39; \

--header &39; \

--header &39; \

--data-raw &34;dialogRequestId&34;notificationType&34;botProtocol&34;templateId&34;AudioPlayer.Play&34;debug&34;templateParams&34;type&34;AudioPlayer.Play&34;playBehavior&34;REPLACE_ALL&34;audioItem&34;stream&34;url&34;token&34;7de36bb44852ae287028ba830565a6ef&34;playInfo&34;content&34;title&34;音頻測試&34;titleSubtext1&34;音頻&39;


小結

許多工作和技術上的爭執源自概念的混淆,技術上的概念不同於文學作品——「每個人眼中都有一個自己的哈姆雷特」。討論問題的基礎好像應該是,澄清概念和明確問題的領域邊界。

異步是一個常見的概念,但在不同的場景中有著不同的含義,本文梳理一下相關內容,試圖可以澄清一些。

相關焦點

  • 聊聊同步、異步、阻塞與非阻塞
    、異步、阻塞與非阻塞近來遇到了一些常見的概念,尤其是網絡編程方面的概念,如:阻塞、非阻塞、異步I/O等等,對於這些概念自己也沒有太清晰的認識,只是很模糊的概念,說了解吧也了解,但是要讓自己準確的描述概念方面的具體細節,卻說的不那麼準確,這也是自己在這幾個方面也沒有細細考究過的原因吧
  • JavaScript 中的異步原理
    來源:極鏈科技作者:周哲所謂「異步」 ,簡單說就是一個任務分成兩段,先執行第一段,然後轉而執行其他任務,等做好了準備,再回過頭執行第二段。比如,有一個任務是讀取文件進行處理,異步的執行過程就是下面這樣。
  • 異步電動機的工作原理與結構
    異步電機是一種交流電機,主要作為電動機用。異步電機運行時,在氣隙中的旋轉磁場與轉子繞組之間存在相對運動,依靠電磁感應作用使轉子繞組中感應電流,產生電磁轉矩,從而實現機電能量的轉換。由於轉子的轉速與旋轉磁場的轉速不相等,所以稱它為異步電機。又因它的轉子電流是靠電磁感應作用產生的,因此,異步電機也稱為感應電機。
  • 三相異步電機的工作原理
    1、三相異步電機的基本原理為了說明異步電機的基本原理,先做一個簡單的實驗。圖6-15是一個裝有手柄的馬蹄形磁鐵,在它的兩極間放著一一個可以自由轉動的,由許多銅條組成的導體。從上面的實驗中知道,磁鐵的旋轉,實質是磁場在旋轉,即旋轉的磁場使轉子導體中產生了感應電流,而載流導體又在磁場中受到電磁力的作用,使轉子旋轉,這就是異步電機旋轉的基本原理。因為轉子導體中的電流是靠電磁感應產生的,以,這種電機又稱感應電機。
  • python中的異步實踐與在tornado中的應用
    ,只是套用官方文檔中的寫法,最近比較細緻的看了下協程的用法,也將tornado在python3中異步的實踐了一下。這些異步操作的完成時刻並不確定。簡言之,異步意味著無序。這個概念讓我想起了上學時學過的一篇文章,講統籌安排的,比如你現在要燒水,做飯,洗衣服三件事,如果同步的進行,先燒水,在水燒開的過程中你什麼都不做就等著它燒開,然後水燒開以後你再接著做飯,飯做熟的過程中你也是什麼都不幹,就乾等著,飯做熟後再去將洗衣服放入洗衣機中去洗,之後又是乾等著。
  • NODE.JS中的異步理解
    promise解決回調地獄的問第一步、先簡單一點理解,不考慮error的情況obj.then的返回值還是一個promise對象第二步第三步、封裝成函數(函數名叫p比較好)最後catch可以只寫一個理解promise:包裝回調函數promise的問題:雖然解決了回調地獄的問題,但寫法還是稍微有一點繁瑣異步函數的用法
  • 電磁調速異步電機是如何工作的?
    電磁調速異步電動機,是在異步電動機軸上裝一個電磁轉差離合器,控制電磁轉差離合器勵磁繞組中的電流電磁調速異步電動機又稱為滑差電動機。電磁調速電動機調速比大,結構簡單,控制方便,適用於紡織、化工、食品等工業。 直觀地解釋,電磁調速異步電動機是電動機與控制器的組合體,包括電機、離合器和控制裝置,集驅動、傳動和控制於一體。 對於異步電機我們並不陌生,用於電磁調速的電機可以是繞線轉子電機,也可以是單速或多速籠型轉子電機。
  • 三相異步電動機工作原理
    三相異步電機又稱為三相異步感應電機,具有結構簡單,工作性能可靠,便宜耐用,且相比於其他電機更容易維護,我們將學習鼠籠式感應電機是如何運作的。它是由轉子和定子兩個部分組成,定子就是外殼線圈靜止部分組成,當通入三相電流時,就會產生一個類似漩渦一樣的磁場,導線有直流電流通過時會產生一個恆定靜止的磁場,當通過變化的交流電時,就會產生一個變化交變磁場,不同的三相異步感應電機功率,轉速都有差異,特別是轉速,相同輸入電壓,功率相同,但它的轉速不同。
  • 單相異步電動機的基本原理與工作原理
    單相異步電動機  單相異步電動機(single-phase asynchronous motor)是靠220V單相交流電源供電的一類電動機,它適用於只有單相電源(single-phase power)的小型工業設備和家用電器中。
  • 三相異步電動機的工作原理與結構
    工作原理1. 磁鐵旋轉對導體的作用下面通過一個實驗來說明異步電動機的工作原理。實驗如圖1-1(a)所示,在一個馬蹄形的磁鐵中間放置一個帶轉軸的閉合線圈,當搖動手柄來旋轉磁鐵時發現,線圈會跟隨著磁鐵一起轉動。為什麼會出現這種現象呢?
  • 單相異步電機如何才能實現高效率的工作
    磁滯損耗是等效電路在磁通量持續轉變時造成的,單相異步電機中應用的大部分荷載原材料是用以電機轉子鐵芯的鋼,根據降低卷繞薄厚,使磁通密度和變壓器骨架耗損小化。根據淬火採用更強級別的卷繞用鋼以更改晶體構造便于于被磁化,能夠減少單相異步電機磁滯損耗。根據提升含矽鋼片的電阻來降低渦流損耗,但矽成分提升了衝壓模具全過程中的磨具損壞,因為它提升了鋼的硬度。
  • .NET異步編程:使用CPS及yield實現異步
    【IT168 技術】在上一篇文章(.NET中的異步編程:傳統的異步編程)中我們圍觀了傳統的異步編程,感受到了異步編程不是簡單的事情。傳統的異步方式將本來緊湊的代碼都分成兩部分,不僅僅降低了代碼的可讀性,還讓一些基本的程序構造無法使用,所以大部分開發人員在遇到應該使用異步的地方都忍痛割愛。
  • RMxprt在三相異步電動機中的2D電磁場分析
    針對如何才能更好地計算仿真三相異步電動機,求解二維和三維有限元件這一問題。文中以一臺三相異步電動機為藍本,分析RMxprt模塊在三相異步電動機的2D電磁場的應用。將實驗計算結果與有限元結果進行橫向對比,誤差僅0.366 2%,符合工程需要。
  • 單相異步電動機調速常用的幾種方式
    那麼對於單相異步電動機來說,常用的調速方式又有哪些呢?今天我們就來聊聊這個話題。單相異步電動機常用的調速方式1、 串接電阻調速PTC熱敏電阻有一個顯著的特點,就是隨著溫度的升高,阻值逐漸增大。我們就利用其特性在電機控制電路中串接一個合適的PTC電阻來改變電壓,進而改變電機運行速度。
  • 三相異步電動機的基本結構、工作原理、型號及銘牌數據
    三相異步電動機是把電能轉換為機械能的電氣設備。它具有構造簡單,價格低廉,工作穩定可靠,控制維護方便的優點,所以在生產實踐中得到廣泛應用。三相異步電動機分為鼠籠式異步電動機和繞線式異步電動機兩種,在建築工地上使用的電動機,絕大部分都是三相鼠籠式異步電動機。更多電工知識大家可以搜索微信公眾號「電工技術雜貨鋪」,裡面定期分享電工技術相關知識。
  • FPGA異步時鐘設計中的同步策略
    但是實際的工程中,純粹單時鐘系統設計的情況很少,特別是設計模塊與外圍晶片的通信中,跨時鐘域的情況經常不可避免。如果對跨時鐘域帶來的亞穩態、採樣丟失、潛在邏輯錯誤等等一系列問題處理不當,將導致系統無法運行。本文總結出了幾種同步策略來解決跨時鐘域問題。
  • JavaScript 中的異步:Event Loop 及其他
    異步簡單地說,JavaScript 是單線程執行的語言,但在使用中有很多異步執行的情況異步的本質是用其他方式(相對同步)控制程序的執行順序,這與其他語言中的多線程模型不同,所以常常有人對非順序取決於當前 Event Loop Queue 中的隊首。Event Loop Queue 中存放的都是消息,每個消息關聯著一個函數,JavaScript Engine 就按照隊列中的消息順序執行它們,也就是執行 chunk。
  • 異步計數器
    計數器的「模」(用M表示): 二、 計數器的分類1.按計數進位分2.按計數增減分3.按計數器中觸發器翻轉是否同步分7.3.1 異步計數器一、異步二進位計數器1.異步二進位加法計數設計思想JK觸發器組成4位異步二進位加法計數器邏輯電路、工作原理、狀態轉換順序表、工作波形D觸發器組成的4位異步二進位加法計數器
  • Tomcat是如何實現異步Servlet的
    ,那麼我們這篇博客聊聊Tomcat的異步Servlet,Tomcat是如何實現異步Servlet的以及異步Servlet的使用場景。ctx.complete(); } }); }上面的代碼實現了一個異步的Servlet,實現了doGet方法注意在SpringBoot中使用需要再啟動類加上@ServletComponentScan註解來掃描Servlet。既然代碼寫好了,我們來看看實際運行效果。
  • 三相異步電動機的分類_三相異步電動機參數
    三、按機械特性分類   ① 普通籠型異步電動機適用於小容量、轉差率變化小的恆速運行的場所。如鼓風機、離心泵、車床等低啟動轉矩和恆負載的場合。   ②深槽籠型適用於中等容量、啟動轉矩比井通籠型異步電動機稍大的場所。   ③雙籠型異步電動機適用於中、大型籠型轉子電動機。啟動轉矩較大。但最大轉矩稍小。