包含imgolang的詞條

本文目錄一覽:

golang+vue3開發的一個im應用

這是一個開源的前後端分離的IM網頁應用。

服務端:

web端:

米爾頓語言模式

心理導讀:當你將指令嵌入於句子里時,你可以令人更不知不覺地輕鬆傳達,讓這位聽者不會意識到你已經下了指令。以上的訊息對聽者的影響會比較溫和,總比你單獨下達這樣的指令“放鬆”、“覺得比較舒服”好得多。

除了反問後設模式外,米爾頓模式還包含很多其他重要的語言模式。其中最重要的就是假設前提的使用。

一、假設前提

要去辨別一個句子的哪裡是假設的,但不容置疑的方法,就是將句子變成否定的,然後再找出哪些是真的。最簡單的假設前提是“存在”。例如在“傑克吃食物”這個句子里已經假設了“傑克”和“食物”是存在的。如果你讓這個句子變成為否定,你說“沒有,傑克沒有吃食物。”事實是傑克和食物還是存在的。但沒有被疑問到。

假設前提是語言模式最具威力的,尤其是被那些假設自己沒有疑問的人使用之時。一般原則是給這個人很多選擇,但所有的選擇都符合你先假設好的反應。

具體假設前提的例子,特別適用於以下的催眠工作。附錄的模式I有一份完整假設前提的清單。

1、時間的附錄字句:

這種字句都是以下列這樣的詞為開頭的。例如之前(before)、之後(after)、在……期間(during)、當(as)、自從(since)、優先(prior)、當(when)、正值(while)等等。

“當你進入入神狀態時,你真的想坐下來嗎?”這句話讓人將注意力引導到是否要坐下來,而且還假設她會進入深入狀態。

“在你完成這項計劃前,我想和你討論點東西。”這句話假設了你將會完成這項計劃。

2、數字順序:

像另一個(another)、首先(first)、第二(second)、第三(third)等等,都是在暗示順序。

“你可以猜猜看你身體的哪一側會先開始放鬆。”這句話假設了身體的兩側都會放鬆,唯一的問題是哪一邊先而已。

3、“或”的使用,“或”這個字是用來假設,在很多的選項里,至少有一個會發生。

“我不知道你的右手還是左手會不知不覺地舉起來。”這句話假設你的其中一隻手會舉起來;唯一的問題是我到底知不知道舉起來的會是哪一隻。

“你會在洗澡前還是洗澡後刷牙?”這句話假設了你會洗澡還有刷牙;唯一的問題是順序的先後。

4、意識感官用詞(Awareness Predicates):

像知道(know)、察覺(aware)、體會(realize)、注意(notice)等等這類的字眼,可以用來假設其餘的例子。唯一的問題是這個聽者是否意識到了你強調的重點。

“你有沒有體會到你的潛意識已經開始在學習了”

“你知不知道你在過去的生活中已有數次進入入神狀態?”

5、副詞和形容詞:

這類詞彙可以在一個句子的主要句子里做假設。

“你對你那發展中的入神狀態好奇嗎?”這句話假設體正在進入入神狀態;唯一的問題是你好奇與否。

“你進入了深層入神狀態嗎?”這句話假設你是在入神狀態;唯一的問題是你是不是處於深層入神狀態,如此而已。

“你有多容易開始放鬆?”這句話假設你可以放鬆;唯一的問題是容易的程度。

6、時間動詞和副詞的變化:

開始(begin)、結束(end)、停止(stop)、開始(start)、繼續(continue)、進行(proceed)、已經(already)、尚(yet)、還是(still)、再(anymore)等詞彙。

“你可以繼續放鬆。”這句話假設你過去曾對催眠感興趣。

“你還是對催眠有興趣嗎?”這句話假設你過去曾對催眠感興趣

7、評論性形容詞及副詞:

幸運地(fortunately)、好運地(luckily)、無辜地(innocently)、快樂地(happily)、必需的(necessarily)等詞。

“很幸運地,沒有必要去知道一些你要的細節,來幫助你得到它。”這句話假設一切事物都沒問題。

在同一個句子里堆積很多種類的假設問題,會讓這個句子讀起來特別有威力。你的假設愈多,聽者想要解開這個句子或問任何一種假設就愈困難。上面所列的一些句子里,就包含了很多種類的假設前提,而這些句子也會比較有威力。下面的句子就是將很多假設前提疊在一起的例子。

“而且我不知道你需要多久時間才能了解你的潛意識已經學了多少東西,因為在你舒服地繼續放鬆的過程之前知道是不重要的,你也要讓你的其他部分去學習一些可利用而且會讓你快樂的東西。”

二、間接引出模式

下一組米爾頓模式特別適用於不必明顯地要求,就能得到間接的具體反應。

“你可以開始放鬆。”

“我不知道你需多久時間才能覺得比較舒服。”

當你將指令嵌入於句子里時,你可以令人更不知不覺地輕鬆傳達,讓這位聽者不會意識到你已經下了指令。以上的訊息對聽者的影響會比較溫和,總比你單獨下達這樣的指令“放鬆”、“覺得比較舒服”好得多。

1、類比式標記:

使用類比式標記時,若加上嵌入式的命令會更具效力。類比式標記是指你用一些非動詞性的類比性質,將指令從句子中分離出來。你可以利用提高音量在指令前後停頓語氣、改變音調、打個手勢或揚起眉毛等方式來表達。你可以用任何對方認得出來的舉動來表明指令,並得到對方特別的注意。對方並不需要意識到他注意了你的特別動作;事實上,當他接收了你的舉動所傳達的訊息,卻並不自覺時,他將更是全神貫注。

2、嵌入式的問句:

問句就像命令一樣,可以嵌入在較大的句子結構中。

“我有興趣知道你想從催眠中得到什麼?”

“我正在想你會喜歡喝什麼樣的飲料。”

一般來說,人們會回答第一句嵌入式的問句:“你要從催眠中得到什麼?”而不會想到這個問句沒有直接提出來。聽者不會拒絕回答這類的問句,因為這問題附帶在與說話者的好奇心有關的陳述里,因此可以產生一種溫婉且優雅的方式去獲得資訊。

3、否定式命令:

當命令是用否定的語氣下達時,其正面的意義是建立在聽者的反應上。例如,如果人家說:“不要考慮粉紅圓點的花樣”,你就必須想到粉紅圓花樣,以便了解該句話的意義。否定語句並不存在於視覺、聽覺及感覺原生經驗里;否定語句能用於次生的經驗:例如語言及數學之類的記號表象。

否定命令可以有效地用在表示確實想要發生的事上,而且要在陳述的前面加上“不”這個字。

“我不要你感到太舒服。”

“不要在練習否定命令時,感到很有趣。”

通常聽者會因為體會什麼是舒服的感覺而有反應,或者是把否定命令的有趣練習當作是了解句子的方式。

4、會話式假設(Conversational Postulates):

是/否問句就是會話式假設,典型作法是誘導出反應,而不是字面上的問答。例如,如果你在街上趨前問人:“你知道時間嗎?”人家就不會說“是”或“否”,她會告訴你現在是幾點。

如果你問人家的是:“你知道今天晚上的電視演什麼?”很可能他告訴你的就是今晚的節目,而不是“是”或“否”。

進行會話式假設前,你要先想想你要是什麼樣的反應。比如說你要某人關門好了。

第二步要做的事,就至少檢查一下你是否真的要那個人關門。換言之,就是要檢視什麼是你假設前提的目標。在這情況中,前提為(a)這個人可以去關門(b)門是開的。

第三步是將其中一個假設前提轉成是/否問句:“你能不能去關門?”、“這扇門是開的嗎?”現在你不需要直接去問問題,就能得到你要的反應。

5、含糊性(Ambiguity):

當一個句子、片語或字詞蘊涵著超過一種以上的可能含義時,就產生了含糊性。含糊性是一種重要的工具,可能導致一點輕微的誤解及方向迷惑,這有利於變動的心理狀態。平常的交談中,交代清楚的陳述有很高的評價。在催眠狀態下,相反的反而是真的。任何一點含糊性可能就讓聽者在內心裡用不只一種方法來處理一個訊息。這需要當事人能主動參與開發訊息蘊涵的意義,這就增加了發現對他合適的意義的可能性。還有,可能會有一個或更多的意義將存留在他的潛意識。在這個附錄中,前述的四種模式(名詞化、非特定的動詞、非特定的參考索引及刪減),都具有增加訊息裡頭含糊性的功能。

(1)同音的含糊(Phonological ambiguity)

聽起來相似但字義不同的字詞,會產生同音的含糊。這些詞包括:right(右)/write(寫)/rite(儀式)、I(我)eye(眼睛)、insecurity(不安全)/in security(安全狀態)、red(紅)/read(讀)、there(那裡)/their(他們的)/theyre(他們是)、weight(重量)/wait(等待)、knows(知道)/nose(鼻子)、here(這裡)/hear(聽到)等。

下列詞彙同樣有兩種意義,雖然它們聽起來都相似,而且拼法也一樣:left(左、離去)、duck(鴨、低頭閃避)、down(下、軟毛)、light(光、輕柔的)。

在一些句子中可以發現其他同音含糊的例子,例如:可能用在主動詞的“Lift your arm”(舉起你的手),或是用在標準動詞的“give me a lift”(助我一臂之力)。其他類似例子有push(推)、pull(拉)、point(點)、touch(碰)、rest(其餘的)、nodl(點頭)、move(移動)、talk(說話)、hand(手)、feel(感覺)。

具有同音含糊性的字詞可以推理來點明,並且與其他字眼組合成另一個不同的訊息,例如“我(“I”不知道你對“入神”一詞的了解也多貼近(close)現在(now)通用的含義。”這裡所點出的訊息可以被聽成“eye close now”(現在閉上眼睛)。

(2)造句法的含糊(Syntactic ambiguity)

造句上含糊的典型例子是“正在催眠中的催眠師可是要具備技巧的。”這句話的意思是可以是催眠師施催眠術需要高度技巧,也可以是要讓催眠師入神需要技巧。

下面的句子有類似的形式“They were milking cows”(“他們在擠牛奶”或“它們是乳牛”)。代名詞“他(它)們”可以指人或者牛。

這類型的含糊性是基於將一個動詞加上進行式形式,置於一個名詞之前,這種加上-ing的動詞可以當作形容詞或是動詞使用。

(3)範圍的含糊(Scope ambiguity)

尺度的含糊性發生在應用形容詞、動詞或副詞的程度的大小不清楚時。

“我們將和這些迷人的男士們和女士們去”,可以說成“我們將和迷人的男士們和女士們去”(也許女士們並不算迷人),或是“和我們去的男士及女士們都是很迷人的。”

“我不知道你將多快就了解到你正舒服地坐在這,傾聽着我的聲音。而且你將很快地進入深層入神狀態,快得一如你的內在潛意識所需。”這並不清楚“了解”這動詞是否意味着了解整句內容所指的,還是在“而且”之前的那部分。如果“了解”意指全句,其假設前提就是用在“了解”一詞之後的都在內。

(4)連結的含糊(Punctuation ambiguity)

在兩個共同一個詞的句子中,將其句尾及句首放在一起用可產生這類含糊性。“Your coat looks like it is made of goose down deeply into trance.”(你的外套看起來是用被深深催眠的鵝的毛做的)。這裡的“down”這個是前面那句“Your coat looks like it is made of goose down”(你的外套看起來是用鵝毛做的)的句尾,也是氣候所接的“down deeply into trance”的字首。“Thats right now youre already begun to relax.”(就是現在,你已經開始放鬆。)

“Im speaking clearly to make sure that you can hear you are in the process of hypnosis.”(在催眠過程中,我正清楚的說話以確定你能聽見)“How are you able to go into a deep trance?”(你是如何進入深度入神狀態的呢?)

三、隱喻的模型

最後一組範例有如使用其他類型的催眠一般,在使用隱喻式交談時特別有用。其他許多模式是在令人深刻的敘說故事中用得到,然而下面;兩則通常認為是屬於米爾頓模式的一部分。

(一)屬性限制的違論(Selectional Restriction Violations):

這裡指的是:某些事物或人的性質歸屬已經被定義成不可能具有那些性質。例如,如果我談到一塊非常傷心的石頭或一個懷孕的男人,我就是違背了它們屬性的限制。因為石頭不會有感覺上的經驗,而男人也不會懷孕。聽眾必須去發掘該敘述的弦外之音。如果我談論的是一顆傷心的石頭所擁有的經驗,以及造成的改變,聽眾可能會跳出我的陳述而聯想應用到他自己的身上。“石頭是不會悲傷的,所以指的是我”,這不是一種自動產生以解所聽聞的方式。、

(二)引用語:

這類模式牽涉到對別人說話時,引用了某段陳述,就好像在報道某人在某時某地說了什麼話一樣。

引用語可以用在傳達任何無附帶責任的訊息上,因此你明顯的談論了某人曾說過的話,你的聽者將因該訊息而有反應,但不會自覺地去辨別他所反應的,或是對這訊息負有責任。

Go number

Go中數值類型可細分為整數、浮點數、複數三種,每種都具有不同的大小範圍和正負支持。

整型分為兩大類

Go提供了有符號和無符號的整數類型,同時提供四種大小不同的整數類型。

取值範圍

等價類型

特殊整型

int 和 uint 分別對應特定CPU平台的字長(機器字大小),大小範圍在 32bit 或 64bit 之間變化,實際開發中由於編譯器和硬件不同而不同。

進制轉換

轉換函數

使用注意

字節長度

Golang提供了兩種精度的浮點數分別為 float32 和 float64 ,它們的算術規範由IEEE754浮點數國際標準定義,IEEE754浮點數標準被現代CPU支持。

float32 類型的浮點數可提供約6個十進制數的精度, float64 類型的浮點數可提供約15個十進制數的精度。通常會優先選擇使用 float64 ,因為 float32 累計計算誤差會比較容易擴散。

計算機中複數(complex)由兩個浮點數表示,一個表示實部(real)一個表示虛部(imag)。

Go語言中複數的值由三部分組成 RE + IMi ,分別是實數部分 RE 、虛數部分 IM 、虛數單位 i , RE 和 IM 均為 float 。

Go語言提供兩種類型的複數,分別是 complex64 即32位實數和虛數, complex128 即64位實數和虛數, complex128 為複數的默認類型。

複數聲明

z 表示複數的變量名, complex128 表示複數類型, complex() 內置函數用於為複數賦值。 x 和 y 分別表示構成該複數的兩個 float64 類型的值, x 為實部, y 為虛部。

簡寫形式

對於 z 值可通過內置函數 real(z) 獲取該複數的實部,使用 imag(z) 獲取虛部。

如何實現支持數億用戶的長連消息系統

此文是根據周洋在【高可用架構群】中的分享內容整理而成,轉發請註明出處。周洋,360手機助手技術經理及架構師,負責360長連接消息系統,360手機助手架構的開發與維護。不知道咱們群名什麼時候改為“Python高可用架構群”了,所以不得不說,很榮幸能在接下來的一個小時里在Python群里討論golang….360消息系統介紹360消息系統更確切的說是長連接push系統,目前服務於360內部多個產品,開發平台數千款app,也支持部分聊天業務場景,單通道多app復用,支持上行數據,提供接入方不同粒度的上行數據和用戶狀態回調服務。目前整個系統按不同業務分成9個功能完整的集群,部署在多個idc上(每個集群覆蓋不同的idc),實時在線數億量級。通常情況下,pc,手機,甚至是智能硬件上的360產品的push消息,基本上是從我們系統發出的。關於push系統對比與性能指標的討論很多同行比較關心go語言在實現push系統上的性能問題,單機性能究竟如何,能否和其他語言實現的類似系統做對比么?甚至問如果是創業,第三方雲推送平台,推薦哪個?其實各大廠都有類似的push系統,市場上也有類似功能的雲服務。包括我們公司早期也有erlang,nodejs實現的類似系統,也一度被公司要求做類似的對比測試。我感覺在討論對比數據的時候,很難保證大家環境和需求的統一,我只能說下我這裡的體會,數據是有的,但這個數據前面估計會有很多定語~第一個重要指標:單機的連接數指標做過長連接的同行,應該有體會,如果在穩定連接情況下,連接數這個指標,在沒有網絡吞吐情況下對比,其實意義往往不大,維持連接消耗cpu資源很小,每條連接tcp協議棧會佔約4k的內存開銷,系統參數調整後,我們單機測試數據,最高也是可以達到單實例300w長連接。但做更高的測試,我個人感覺意義不大。因為實際網絡環境下,單實例300w長連接,從理論上算壓力就很大:實際弱網絡環境下,移動客戶端的斷線率很高,假設每秒有1000分之一的用戶斷線重連。300w長連接,每秒新建連接達到3w,這同時連入的3w用戶,要進行註冊,加載離線存儲等對內rpc調用,另外300w長連接的用戶心跳需要維持,假設心跳300s一次,心跳包每秒需要1w tps。單播和多播數據的轉發,廣播數據的轉發,本身也要響應內部的rpc調用,300w長連接情況下,gc帶來的壓力,內部接口的響應延遲能否穩定保障。這些集中在一個實例中,可用性是一個挑戰。所以線上單實例不會hold很高的長連接,實際情況也要根據接入客戶端網絡狀況來決定。第二個重要指標:消息系統的內存使用量指標這一點上,使用go語言情況下,由於協程的原因,會有一部分額外開銷。但是要做兩個推送系統的對比,也有些需要確定問題。比如系統從設計上是否需要全雙工(即讀寫是否需要同時進行)如果半雙工,理論上對一個用戶的連接只需要使用一個協程即可(這種情況下,對用戶的斷線檢測可能會有延時),如果是全雙工,那讀/寫各一個協程。兩種場景內存開銷是有區別的。另外測試數據的大小往往決定我們對連接上設置的讀寫buffer是多大,是全局復用的,還是每個連接上獨享的,還是動態申請的。另外是否全雙工也決定buffer怎麼開。不同的策略,可能在不同情況的測試中表現不一樣。第三個重要指標:每秒消息下發量這一點上,也要看我們對消息到達的QoS級別(回復ack策略區別),另外看架構策略,每種策略有其更適用的場景,是純粹推?還是推拉結合?甚至是否開啟了消息日誌?日誌庫的實現機制、以及緩衝開多大?flush策略……這些都影響整個系統的吞吐量。另外為了HA,增加了內部通信成本,為了避免一些小概率事件,提供閃斷補償策略,這些都要考慮進去。如果所有的都去掉,那就是比較基礎庫的性能了。所以我只能給出大概數據,24核,64G的服務器上,在QoS為message at least,純粹推,消息體256B~1kB情況下,單個實例100w實際用戶(200w+)協程,峰值可以達到2~5w的QPS…內存可以穩定在25G左右,gc時間在200~800ms左右(還有優化空間)。我們正常線上單實例用戶控制在80w以內,單機最多兩個實例。事實上,整個系統在推送的需求上,對高峰的輸出不是提速,往往是進行限速,以防push系統瞬時的高吞吐量,轉化成對接入方業務服務器的ddos攻擊所以對於性能上,我感覺大家可以放心使用,至少在我們這個量級上,經受過考驗,go1.5到來後,確實有之前投資又增值了的感覺。消息系統架構介紹下面是對消息系統的大概介紹,之前一些同學可能在gopher china上可以看到分享,這裡簡單講解下架構和各個組件功能,額外補充一些當時遺漏的信息:架構圖如下,所有的service都 written by golang.幾個大概重要組件介紹如下:dispatcher service根據客戶端請求信息,將應網絡和區域的長連接服務器的,一組IP傳送給客戶端。客戶端根據返回的IP,建立長連接,連接Room service.room Service,長連接網關,hold用戶連接,並將用戶註冊進register service,本身也做一些接入安全策略、白名單、IP限制等。register service是我們全局session存儲組件,存儲和索引用戶的相關信息,以供獲取和查詢。coordinator service用來轉發用戶的上行數據,包括接入方訂閱的用戶狀態信息的回調,另外做需要協調各個組件的異步操作,比如kick用戶操作,需要從register拿出其他用戶做異步操作.saver service是存儲訪問層,承擔了對redis和mysql的操作,另外也提供部分業務邏輯相關的內存緩存,比如廣播信息的加載可以在saver中進行緩存。另外一些策略,比如客戶端sdk由於被惡意或者意外修改,每次加載了消息,不回復ack,那服務端就不會刪除消息,消息就會被反覆加載,形成死循環,可以通過在saver中做策略和判斷。(客戶端總是不可信的)。center service提供給接入方的內部api服務器,比如單播或者廣播接口,狀態查詢接口等一系列api,包括運維和管理的api。舉兩個常見例子,了解工作機制:比如發一條單播給一個用戶,center先請求Register獲取這個用戶之前註冊的連接通道標識、room實例地址,通過room service下發給長連接 Center Service比較重的工作如全網廣播,需要把所有的任務分解成一系列的子任務,分發給所有center,然後在所有的子任務里,分別獲取在線和離線的所有用戶,再批量推到Room Service。通常整個集群在那一瞬間壓力很大。deployd/agent service用於部署管理各個進程,收集各組件的狀態和信息,zookeeper和keeper用於整個系統的配置文件管理和簡單調度關於推送的服務端架構常見的推送模型有長輪訓拉取,服務端直接推送(360消息系統目前主要是這種),推拉結合(推送只發通知,推送後根據通知去拉取消息).拉取的方式不說了,現在並不常用了,早期很多是nginx+lua+redis,長輪訓,主要問題是開銷比較大,時效性也不好,能做的優化策略不多。直接推送的系統,目前就是360消息系統這種,消息類型是消耗型的,並且對於同一個用戶並不允許重複消耗,如果需要多終端重複消耗,需要抽象成不同用戶。推的好處是實時性好,開銷小,直接將消息下發給客戶端,不需要客戶端走從接入層到存儲層主動拉取.但純推送模型,有個很大問題,由於系統是異步的,他的時序性無法精確保證。這對於push需求來說是夠用的,但如果復用推送系統做im類型通信,可能並不合適。對於嚴格要求時序性,消息可以重複消耗的系統,目前也都是走推拉結合的模型,就是只使用我們的推送系統發通知,並附帶id等給客戶端做拉取的判斷策略,客戶端根據推送的key,主動從業務服務器拉取消息。並且當主從同步延遲的時候,跟進推送的key做延遲拉取策略。同時也可以通過消息本身的QoS,做純粹的推送策略,比如一些“正在打字的”低優先級消息,不需要主動拉取了,通過推送直接消耗掉。哪些因素決定推送系統的效果?首先是sdk的完善程度,sdk策略和細節完善度,往往決定了弱網絡環境下最終推送質量.SDK選路策略,最基本的一些策略如下:有些開源服務可能會針對用戶hash一個該接入區域的固定ip,實際上在國內環境下不可行,最好分配器(dispatcher)是返回散列的一組,而且端口也要參開,必要時候,客戶端告知是retry多組都連不上,返回不同idc的服務器。因為我們會經常檢測到一些case,同一地區的不同用戶,可能對同一idc內的不同ip連通性都不一樣,也出現過同一ip不同端口連通性不同,所以用戶的選路策略一定要靈活,策略要足夠完善.另外在選路過程中,客戶端要對不同網絡情況下的長連接ip做緩存,當網絡環境切換時候(wifi、2G、3G),重新請求分配器,緩存不同網絡環境的長連接ip。客戶端對於數據心跳和讀寫超時設置,完善斷線檢測重連機制針對不同網絡環境,或者客戶端本身消息的活躍程度,心跳要自適應的進行調整並與服務端協商,來保證鏈路的連通性。並且在弱網絡環境下,除了網絡切換(wifi切3G)或者讀寫出錯情況,什麼時候重新建立鏈路也是一個問題。客戶端發出的ping包,不同網絡下,多久沒有得到響應,認為網絡出現問題,重新建立鏈路需要有個權衡。另外對於不同網絡環境下,讀取不同的消息長度,也要有不同的容忍時間,不能一刀切。好的心跳和讀寫超時設置,可以讓客戶端最快的檢測到網絡問題,重新建立鏈路,同時在網絡抖動情況下也能完成大數據傳輸。結合服務端做策略另外系統可能結合服務端做一些特殊的策略,比如我們在選路時候,我們會將同一個用戶盡量映射到同一個room service實例上。斷線時,客戶端盡量對上次連接成功的地址進行重試。主要是方便服務端做閃斷情況下策略,會暫存用戶閃斷時實例上的信息,重新連入的 時候,做單實例內的遷移,減少延時與加載開銷.客戶端保活策略很多創業公司願意重新搭建一套push系統,確實不難實現,其實在協議完備情況下(最簡單就是客戶端不回ack不清數據),服務端會保證消息是不丟的。但問題是為什麼在消息有效期內,到達率上不去?往往因為自己app的push service存活能力不高。選用雲平台或者大廠的,往往sdk會做一些保活策略,比如和其他app共生,互相喚醒,這也是雲平台的push service更有保障原因。我相信很多雲平台旗下的sdk,多個使用同樣sdk的app,為了實現服務存活,是可以互相喚醒和保證活躍的。另外現在push sdk本身是單連接,多app復用的,這為sdk實現,增加了新的挑戰。綜上,對我來說,選擇推送平台,優先會考慮客戶端sdk的完善程度。對於服務端,選擇條件稍微簡單,要求部署接入點(IDC)越要多,配合精細的選路策略,效果越有保證,至於想知道哪些雲服務有多少點,這個群里來自各地的小夥伴們,可以合夥測測。go語言開發問題與解決方案下面講下,go開發過程中遇到挑戰和優化策略,給大家看下當年的一張圖,在第一版優化方案上線前一天截圖~可以看到,內存最高佔用69G,GC時間單實例最高時候高達3~6s.這種情況下,試想一次悲劇的請求,經過了幾個正在執行gc的組件,後果必然是超時… gc照成的接入方重試,又加重了系統的負擔。遇到這種情況當時整個系統最差情況每隔2,3天就需要重啟一次~當時出現問題,現在總結起來,大概以下幾點1.散落在協程里的I/O,Buffer和對象不復用。當時(12年)由於對go的gc效率理解有限,比較奔放,程序里大量short live的協程,對內通信的很多io操作,由於不想阻塞主循環邏輯或者需要及時響應的邏輯,通過單獨go協程來實現異步。這回會gc帶來很多負擔。針對這個問題,應盡量控制協程創建,對於長連接這種應用,本身已經有幾百萬並發協程情況下,很多情況沒必要在各個並發協程內部做異步io,因為程序的並行度是有限,理論上做協程內做阻塞操作是沒問題。如果有些需要異步執行,比如如果不異步執行,影響對用戶心跳或者等待response無法響應,最好通過一個任務池,和一組常駐協程,來消耗,處理結果,通過channel再傳回調用方。使用任務池還有額外的好處,可以對請求進行打包處理,提高吞吐量,並且可以加入控量策略.2.網絡環境不好引起激增go協程相比較以往高並發程序,如果做不好流控,會引起協程數量激增。早期的時候也會發現,時不時有部分主機內存會遠遠大於其他服務器,但發現時候,所有主要profiling參數都正常了。後來發現,通信較多系統中,網絡抖動阻塞是不可免的(即使是內網),對外不停accept接受新請求,但執行過程中,由於對內通信阻塞,大量協程被 創建,業務協程等待通信結果沒有釋放,往往瞬時會迎來協程暴漲。但這些內存在系統穩定後,virt和res都並沒能徹底釋放,下降後,維持高位。處理這種情況,需要增加一些流控策略,流控策略可以選擇在rpc庫來做,或者上面說的任務池來做,其實我感覺放在任務池裡做更合理些,畢竟rpc通信庫可以做讀寫數據的限流,但它並不清楚具體的限流策略,到底是重試還是日誌還是緩存到指定隊列。任務池本身就是業務邏輯相關的,它清楚針對不同的接口需要的流控限制策略。3.低效和開銷大的rpc框架早期rpc通信框架比較簡單,對內通信時候使用的也是短連接。這本來短連接開銷和性能瓶頸超出我們預期,短連接io效率是低一些,但端口資源夠,本身吞吐可以滿足需要,用是沒問題的,很多分層的系統,也有http短連接對內進行請求的但早期go版本,這樣寫程序,在一定量級情況,是支撐不住的。短連接大量臨時對象和臨時buffer創建,在本已經百萬協程的程序中,是無法承受的。所以後續我們對我們的rpc框架作了兩次調整。第二版的rpc框架,使用了連接池,通過長連接對內進行通信(復用的資源包括client和server的:編解碼Buffer、Request/response),大大改善了性能。但這種在一次request和response還是佔用連接的,如果網絡狀況ok情況下,這不是問題,足夠滿足需要了,但試想一個room實例要與後面的數百個的register,coordinator,saver,center,keeper實例進行通信,需要建立大量的常駐連接,每個目標機幾十個連接,也有數千個連接被佔用。非持續抖動時候(持續逗開多少無解),或者有延遲較高的請求時候,如果針對目標ip連接開少了,會有瞬時大量請求阻塞,連接無法得到充分利用。第三版增加了Pipeline操作,Pipeline會帶來一些額外的開銷,利用tcp的全雙特性,以盡量少的連接完成對各個服務集群的rpc調用。4.Gc時間過長Go的Gc仍舊在持續改善中,大量對象和buffer創建,仍舊會給gc帶來很大負擔,尤其一個佔用了25G左右的程序。之前go team的大咖郵件也告知我們,未來會讓使用協程的成本更低,理論上不需要在應用層做更多的策略來緩解gc.改善方式,一種是多實例的拆分,如果公司沒有端口限制,可以很快部署大量實例,減少gc時長,最直接方法。不過對於360來說,外網通常只能使用80和433。因此常規上只能開啟兩個實例。當然很多人給我建議能否使用SO_REUSEPORT,不過我們內核版本確實比較低,並沒有實踐過。另外能否模仿nginx,fork多個進程監控同樣端口,至少我們目前沒有這樣做,主要對於我們目前進程管理上,還是獨立的運行的,對外監聽不同端口程序,還有配套的內部通信和管理端口,實例管理和升級上要做調整。解決gc的另兩個手段,是內存池和對象池,不過最好做仔細評估和測試,內存池、對象池使用,也需要對於代碼可讀性與整體效率進行權衡。這種程序一定情況下會降低並行度,因為用池內資源一定要加互斥鎖或者原子操作做CAS,通常原子操作實測要更快一些。CAS可以理解為可操作的更細行為粒度的鎖(可以做更多CAS策略,放棄運行,防止忙等)。這種方式帶來的問題是,程序的可讀性會越來越像C語言,每次要malloc,各地方用完後要free,對於對象池free之前要reset,我曾經在應用層嘗試做了一個分層次結構的“無鎖隊列”上圖左邊的數組實際上是一個列表,這個列表按大小將內存分塊,然後使用atomic操作進行CAS。但實際要看測試數據了,池技術可以明顯減少臨時對象和內存的申請和釋放,gc時間會減少,但加鎖帶來的並行度的降低,是否能給一段時間內的整體吞吐量帶來提升,要做測試和權衡…在我們消息系統,實際上後續去除了部分這種黑科技,試想在百萬個協程裡面做自旋操作申請復用的buffer和對象,開銷會很大,尤其在協程對線程多對多模型情況下,更依賴於golang本身調度策略,除非我對池增加更多的策略處理,減少忙等,感覺是在把runtime做的事情,在應用層非常不優雅的實現。普遍使用開銷理論就大於收益。但對於rpc庫或者codec庫,任務池內部,這些開定量協程,集中處理數據的區域,可以嘗試改造~對於有些固定對象復用,比如固定的心跳包什麼的,可以考慮使用全局一些對象,進行復用,針對應用層數據,具體設計對象池,在部分環節去復用,可能比這種無差別的設計一個通用池更能進行效果評估.消息系統的運維及測試下面介紹消息系統的架構迭代和一些迭代經驗,由於之前在其他地方有過分享,後面的會給出相關鏈接,下面實際做個簡單介紹,感興趣可以去鏈接裡面看架構迭代~根據業務和集群的拆分,能解決部分灰度部署上線測試,減少點對點通信和廣播通信不同產品的相互影響,針對特定的功能做獨立的優化.消息系統架構和集群拆分,最基本的是拆分多實例,其次是按照業務類型對資源佔用情況分類,按用戶接入網絡和對idc布點要求分類(目前沒有條件,所有的產品都部署到全部idc)系統的測試go語言在並發測試上有獨特優勢。對於壓力測試,目前主要針對指定的服務器,選定線上空閑的服務器做長連接壓測。然後結合可視化,分析壓測過程中的系統狀態。但壓測早期用的比較多,但實現的統計報表功能和我理想有一定差距。我覺得最近出的golang開源產品都符合這種場景,go寫網絡並發程序給大家帶來的便利,讓大家把以往為了降低複雜度,拆解或者分層協作的組件,又組合在了一起。QAQ1:協議棧大小,超時時間定製原則?移動網絡下超時時間按產品需求通常2g,3G情況下是5分鐘,wifi情況下5~8分鐘。但對於個別場景,要求響應非常迅速的場景,如果連接idle超過1分鐘,都會有ping,pong,來校驗是否斷線檢測,儘快做到重新連接。Q2:消息是否持久化?消息持久化,通常是先存後發,存儲用的redis,但落地用的mysql。mysql只做故障恢復使用。Q3:消息風暴怎麼解決的?如果是發送情況下,普通產品是不需要限速的,對於較大產品是有發送隊列做控速度,按人數,按秒進行控速度發放,發送成功再發送下一條。Q4:golang的工具鏈支持怎麼樣?我自己寫過一些小程序千把行之內,確實很不錯,但不知道代碼量上去之後,配套的debug工具和profiling工具如何,我看上邊有分享說golang自帶的profiling工具還不錯,那debug呢怎麼樣呢,官方一直沒有出debug工具,gdb支持也不完善,不知你們用的什麼?是這樣的,我們正常就是println,我感覺基本上可以定位我所有問題,但也不排除由於並行性通過println無法復現的問題,目前來看只能靠經驗了。只要常見並發嘗試,經過分析是可以找到的。go很快會推出調試工具的~Q5:協議棧是基於tcp嗎?是否有協議拓展功能?協議棧是tcp,整個系統tcp長連接,沒有考慮擴展其功能~如果有好的經驗,可以分享~Q6:問個問題,這個系統是接收上行數據的吧,系統接收上行數據後是轉發給相應系統做處理么,是怎麼轉發呢,如果需要給客戶端返回調用結果又是怎麼處理呢?系統上行數據是根據協議頭進行轉發,協議頭裡面標記了產品和轉發類型,在coordinator裡面跟進產品和轉發類型,回調用戶,如果用戶需要阻塞等待回復才能後續操作,那通過再發送消息,路由回用戶。因為整個系統是全異步的。Q7:問個pushsdk的問題。pushsdk的單連接,多app復用方式,這樣的情況下以下幾個問題是如何解決的:1)系統流量統計會把所有流量都算到啟動連接的應用吧?而啟動應用的連接是不固定的吧?2)同一個pushsdk在不同的應用中的版本號可能不一樣,這樣暴露出來的接口可能有版本問題,如果用單連接模式怎麼解決?流量只能算在啟動的app上了,但一般這種安裝率很高的app承擔可能性大,常用app本身被檢測和殺死可能性較少,另外消息下發量是有嚴格控制 的。整體上用戶還是省電和省流量的。我們pushsdk盡量向上兼容,出於這個目的,push sdk本身做的工作非常有限,抽象出來一些常見的功能,純推的系統,客戶端策略目前做的很少,也有這個原因。Q8:生產系統的profiling是一直打開的么?不是一直打開,每個集群都有採樣,但需要開啟哪個可以後台控制。這個profling是通過接口調用。Q9:面前系統中的消息消費者可不可以分組?類似於Kafka。客戶端可以訂閱不同產品的消息,接受不同的分組。接入的時候進行bind或者unbind操作Q10:為什麼放棄erlang,而選擇go,有什麼特別原因嗎?我們現在用的erlang?erlang沒有問題,原因是我們上線後,其他團隊才做出來,經過qa一個部門對比測試,在沒有顯著性能提升下,選擇繼續使用go版本的push,作為公司基礎服務。Q11:流控問題有排查過網卡配置導致的idle問題嗎?流控是業務級別的流控,我們上線前對於內網的極限通信量做了測試,後續將請求在rpc庫內,控制在小於內部通信開銷的上限以下.在到達上限前作流控。Q12:服務的協調調度為什麼選擇zk有考慮過raft實現嗎?golang的raft實現很多啊,比如Consul和ectd之類的。3年前,還沒有後兩者或者後兩者沒聽過應該。zk當時公司內部成熟方案,不過目前來看,我們不準備用zk作結合系統的定製開發,準備用自己寫的keeper代替zk,完成配置文件自動轉數據結構,數據結構自動同步指定進程,同時裡面可以完成很多自定義的發現和控制策略,客戶端包含keeper的sdk就可以實現以上的所有監控數據,profling數據收集,配置文件更新,啟動關閉等回調。完全抽象成語keeper通信sdk,keeper之間考慮用raft。Q13:負載策略是否同時在服務側與CLIENT側同時做的 (DISPATCHER 會返回一組IP)?另外,ROOM SERVER/REGISTER SERVER連接狀態的一致性可用性如何保證? 服務側保活有無特別關注的地方? 安全性方面是基於TLS再加上應用層加密?會在server端做,比如重啟操作前,會下髮指令類型消息,讓客戶端進行主動行為。部分消息使用了加密策略,自定義的rsa+des,另外滿足我們安全公司的需要,也定製開發很多安全加密策略。一致性是通過冷備解決的,早期考慮雙寫,但實時狀態雙寫同步代價太高而且容易有臟數據,比如register掛了,調用所有room,通過重新刷入指定register來解決。Q14:這個keeper有開源打算嗎?還在寫,如果沒耦合我們系統太多功能,一定會開源的,主要這意味着,我們所有的bind在sdk的庫也需要開源~Q15:比較好奇lisence是哪個如果開源?

有什麼中英文互助交流平台么

一,qq英語聊天室,水平不怎麼高,適合初學者不過都是幫中國人自己跟自己聊。

二,MSN老外有些人用的,但是也不多,用的多的還是ICQ,有個大學生的msn口語群可以加一下(group174990@hotmail.com)(msngroup2266@hotmail.com),裡面有老外,美國的,歐洲的,東南亞,韓國的都有,而且每天大部分時間都能找到人聊。老外出現率較qq高,但是水平一般,偶有高手和一些留學在裡面。

三,如果你夠水平,而求深諳美國文化或者外國文化,那麼建議下載一個paltalk聊天軟件,免費的,裡面全是老外,不過不怎麼插的上話,應為你先要知道很多老外喜歡聊天的縮寫,比如wb(welcome back) yvw(you are very welcome) lol(laughing out loud)等等。強力推薦。

四,如果你想說的話,msn上有好多的語音口語聊天室,水平都了得的人才有資格進。

五,skype也可以,但是是打電話為主的軟件

這可能是最全的golang的”==”比較規則了吧

大家經常用”==”來比較兩個變量是否相等。但是golang中的”==”有很多細節的地方,跟php是不一樣的。很多時候不能直接用”==”來比較,編譯器會直接報錯。

golang中基本類型的比較規則和複合類型的不一致,先介紹下golang的變量類型:

golang中的基本類型

比較的兩個變量類型必須相等。而且,golang沒有隱式類型轉換,比較的兩個變量必須類型完全一樣,類型別名也不行。如果要比較,先做類型轉換再比較。

複合類型是逐個字段,逐個元素比較的。需要注意的是, array 或者struct中每個元素必須要是可比較的,如果某個array的元素 or struct的成員不能比較(比如是後面介紹的slice,map等),則此複合類型也不能比較。

逐個成員比較類型和值。每個對應成員的比較遵循基本類型變量的比較規則。

但是如果struct中有不可比較的成員類型時:

可以看到,struct中有slice這種不可比較的成員時,整個struct都不能做比較,即使沒有對slice那個成員賦值(slice默認值為nil)

slice和map的比較規則比較奇怪,我們先說普通的變量引用類型val和channel的比較規則。

引用類型變量存儲的是某個變量的內存地址。所以引用類型變量的比較,判斷的是這兩個引用類型存儲的是不是同一個變量。

上面看起來比較廢話,但是得理解引用類型的含義。不然對判斷規則還是不清楚。

slice類型不可比較,只能與零值nil做比較。

關於slice類型不可比較的原因,後面會專門寫文章做討論。

map類型和slice一樣,不能比較,只能與nil做比較。

接口類型的變量,包含該接口變量存儲的值和值的類型兩部分組成,分別稱為接口的動態類型和動態值。 只有動態類型和動態值都相同時,兩個接口變量才相同:

而且接口的動態類型必須要是可比較的,如果不能比較(比如slice,map),則運行時會報panic。因為編譯器在編譯時無法獲取接口的動態類型,所以編譯能通過,但是運行時直接panic:

golang的func作為一等公民,也是一種類型,而且不可比較

上面說過,map和slice是不可比較類型,但是有沒有特殊的方法來對slice和map做比較呢,有

reflect.DeepEqual函數可以用來比較兩個任意類型的變量

對map類型做比較:

對slice類型做比較:

對struct類型做比較:

可以發現,只要變量的類型和值相同的話,reflect.DeepEqual比較的結果就為true

直接看用例:

結果為:

1, golang的類型再定義和類型別名

2,golang的slice和map為什麼不可以比較

1,

2,

3,

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/280427.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-21 13:03
下一篇 2024-12-21 13:03

相關推薦

發表回復

登錄後才能評論