本教程介紹 Go 中多模塊工作區的基礎知識。使用多模塊工作區,您可以告訴 Go 命令您正在同時在多個模塊中編寫代碼,并輕松地在這些模塊中構建和運行代碼。
創新互聯建站是專業的青川網站建設公司,青川接單;提供網站設計、做網站,網頁設計,網站設計,建網站,PHP網站建設等專業做網站服務;采用PHP框架,可快速的進行青川網站開發網頁制作和功能擴展;專業做搜索引擎喜愛的網站,專業的做網站團隊,希望更多企業前來合作!
在本教程中,您將在共享的多模塊工作區中創建兩個模塊,對這些模塊進行更改,并在構建中查看這些更改的結果。
本教程需要 go1.18 或更高版本。使用go.dev/dl中的鏈接確保您已在 Go 1.18 或更高版本中安裝了 Go 。
首先,為您要編寫的代碼創建一個模塊。
1、打開命令提示符并切換到您的主目錄。
在 Linux 或 Mac 上:
在 Windows 上:
2、在命令提示符下,為您的代碼創建一個名為工作區的目錄。
3、初始化模塊
我們的示例將創建一個hello依賴于 golang.org/x/example 模塊的新模塊。
創建你好模塊:
使用 . 添加對 golang.org/x/example 模塊的依賴項go get。
在 hello 目錄下創建 hello.go,內容如下:
現在,運行 hello 程序:
在這一步中,我們將創建一個go.work文件來指定模塊的工作區。
在workspace目錄中,運行:
該go work init命令告訴為包含目錄中模塊的工作空間go創建一個文件 。go.work./hello
該go命令生成一個go.work如下所示的文件:
該go.work文件的語法與go.mod相同。
該go指令告訴 Go 應該使用哪個版本的 Go 來解釋文件。它類似于文件中的go指令go.mod 。
該use指令告訴 Go在進行構建時hello目錄中的模塊應該是主模塊。
所以在模塊的任何子目錄中workspace都會被激活。
2、運行工作區目錄下的程序
在workspace目錄中,運行:
Go 命令包括工作區中的所有模塊作為主模塊。這允許我們在模塊中引用一個包,即使在模塊之外。在模塊或工作區之外運行go run命令會導致錯誤,因為該go命令不知道要使用哪些模塊。
接下來,我們將golang.org/x/example模塊的本地副本添加到工作區。然后,我們將向stringutil包中添加一個新函數,我們可以使用它來代替Reverse.
在這一步中,我們將下載包含該模塊的 Git 存儲庫的副本golang.org/x/example,將其添加到工作區,然后向其中添加一個我們將從 hello 程序中使用的新函數。
1、克隆存儲庫
在工作區目錄中,運行git命令來克隆存儲庫:
2、將模塊添加到工作區
該go work use命令將一個新模塊添加到 go.work 文件中。它現在看起來像這樣:
該模塊現在包括example.com/hello模塊和 `golang.org/x/example 模塊。
這將允許我們使用我們將在模塊副本中編寫的新代碼,而不是使用命令stringutil下載的模塊緩存中的模塊版本。
3、添加新功能。
我們將向golang.org/x/example/stringutil包中添加一個新函數以將字符串大寫。
將新文件夾添加到workspace/example/stringutil包含以下內容的目錄:
4、修改hello程序以使用該功能。
修改workspace/hello/hello.go的內容以包含以下內容:
從工作區目錄,運行
Go 命令在go.work文件指定的hello目錄中查找命令行中指定的example.com/hello模塊 ,同樣使用go.work文件解析導入golang.org/x/example。
go.work可以用來代替添加replace 指令以跨多個模塊工作。
由于這兩個模塊在同一個工作區中,因此很容易在一個模塊中進行更改并在另一個模塊中使用它。
現在,要正確發布這些模塊,我們需要發布golang.org/x/example 模塊,例如在v0.1.0. 這通常通過在模塊的版本控制存儲庫上標記提交來完成。發布完成后,我們可以增加對 golang.org/x/example模塊的要求hello/go.mod:
這樣,該go命令可以正確解析工作區之外的模塊。
Go語言由Google公司開發,并于2009年開源,相比Java/Python/C等語言,Go尤其擅長并發編程,性能堪比C語言,開發效率肩比Python,被譽為“21世紀的C語言”。
Go語言在云計算、大數據、微服務、高并發領域應用應用非常廣泛。BAT大廠正在把Go作為新項目開發的首選語言。
Go語言應用范圍:
1、服務端開發:以前你使用C或者C++做的那些事情,用Go來做很合適,例如日志處理、文件系統、監控系統等;
2、DevOps:運維生態中的Docker、K8s、prometheus、grafana、open-falcon等都是使用Go語言開發;
3、網絡編程:大量優秀的Web框架如Echo、Gin、Iris、beego等,而且Go內置的 net/http包十分的優秀;
4、Paas云平臺領域:Kubernetes和Docker Swarm等;
5、分布式存儲領域:etcd、Groupcache、TiDB、Cockroachdb、Influxdb等;
6、區塊鏈領域:區塊鏈里面有兩個明星項目以太坊和fabric都使用Go語言;
7、容器虛擬化:大名鼎鼎的Docker就是使用Go語言實現的;
8、爬蟲及大數據:Go語言天生支持并發,所以十分適合編寫分布式爬蟲及大數據處理。
此文是根據周洋在【高可用架構群】中的分享內容整理而成,轉發請注明出處。
周洋,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傳送給客戶端??蛻舳烁鶕祷氐腎P,建立長連接,連接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會做一些?;畈呗裕热绾推渌鸻pp共生,互相喚醒,這也是云平臺的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寫網絡并發程序給大家帶來的便利,讓大家把以往為了降低復雜度,拆解或者分層協作的組件,又組合在了一起。
QA
Q1:協議棧大小,超時時間定制原則?
移動網絡下超時時間按產品需求通常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是哪個如果開源?
智能合約調用是實現一個 DApp 的關鍵,一個完整的 DApp 包括前端、后端、智能合約及區塊 鏈系統,智能合約的調用是連接區塊鏈與前后端的關鍵。
我們先來了解一下智能合約調用的基礎原理。智能合約運行在以太坊節點的 EVM 中。因此要 想調用合約必須要訪問某個節點。
以后端程序為例,后端服務若想連接節點有兩種可能,一種是雙 方在同一主機,此時后端連接節點可以采用 本地 IPC(Inter-Process Communication,進 程間通信)機制,也可以采用 RPC(Remote Procedure Call,遠程過程調用)機制;另 一種情況是雙方不在同一臺主機,此時只能采用 RPC 機制進行通信。
提到 RPC, 讀者應該對 Geth 啟動參數有點印象,Geth 啟動時可以選擇開啟 RPC 服務,對應的 默認服務端口是 8545。。
接著,我們來了解一下智能合約運行的過程。
智能合約的運行過程是后端服務連接某節點,將 智能合約的調用(交易)發送給節點,節點在驗證了交易的合法性后進行全網廣播,被礦工打包到 區塊中代表此交易得到確認,至此交易才算完成。
就像數據庫一樣,每個區塊鏈平臺都會提供主流 開發語言的 SDK(Software Development Kit,軟件開發工具包),由于 Geth 本身就是用 Go 語言 編寫的,因此若想使用 Go 語言連接節點、發交易,直接在工程內導入 go-ethereum(Geth 源碼) 包就可以了,剩下的問題就是流程和 API 的事情了。
總結一下,智能合約被調用的兩個關鍵點是節點和 SDK。
由于 IPC 要求后端與節點必須在同一主機,所以很多時候開發者都會采用 RPC 模式。除了 RPC,以太坊也為開發者提供了 json- rpc 接口,本文就不展開討論了。
接下來介紹如何使用 Go 語言,借助 go-ethereum 源碼庫來實現智能合約的調用。這是有固定 步驟的,我們先來說一下總體步驟,以下面的合約為例。
步驟 01:編譯合約,獲取合約 ABI(Application Binary Interface,應用二進制接口)。 單擊【ABI】按鈕拷貝合約 ABI 信息,將其粘貼到文件 calldemo.abi 中(可使用 Go 語言IDE 創建該文件,文件名可自定義,后綴最好使用 abi)。
最好能將 calldemo.abi 單獨保存在一個目錄下,輸入“ls”命令只能看到 calldemo.abi 文件,參 考效果如下:
步驟 02:獲得合約地址。注意要將合約部署到 Geth 節點。因此 Environment 選擇為 Web3 Provider。
在【Environment】選項框中選擇“Web3 Provider”,然后單擊【Deploy】按鈕。
部署后,獲得合約地址為:0xa09209c28AEf59a4653b905792a9a910E78E7407。
步驟 03:利用 abigen 工具(Geth 工具包內的可執行程序)編譯智能合約為 Go 代碼。abigen 工具的作用是將 abi 文件轉換為 Go 代碼,命令如下:
其中各參數的含義如下。 (1)abi:是指定傳入的 abi 文件。 (2)type:是指定輸出文件中的基本結構類型。 (3)pkg:指定輸出文件 package 名稱。 (4)out:指定輸出文件名。 執行后,將在代碼目錄下看到 funcdemo.go 文件,讀者可以打開該文件欣賞一下,注意不要修改它。
步驟 04:創建 main.go,填入如下代碼。 注意代碼中 HexToAddress 函數內要傳入該合約部署后的地址,此地址在步驟 01 中獲得。
步驟 04:設置 go mod,以便工程自動識別。
前面有所提及,若要使用 Go 語言調用智能合約,需要下載 go-ethereum 工程,可以使用下面 的指令:
該指令會自動將 go-ethereum 下載到“$GOPATH/src/github.com/ethereum/go-ethereum”,這樣還算 不錯。不過,Go 語言自 1.11 版本后,增加了 module 管理工程的模式。只要設置好了 go mod,下載 依賴工程的事情就不必關心了。
接下來設置 module 生效和 GOPROXY,命令如下:
在項目工程內,執行初始化,calldemo 可以自定義名稱。
步驟 05:運行代碼。執行代碼,將看到下面的效果,以及最終輸出的 2020。
上述輸出信息中,可以看到 Go 語言會自動下載依賴文件,這就是 go mod 的神奇之處??吹?2020,相信讀者也知道運行結果是正確的了。
作為一個測試,作為一個測試開發, 全棧化+管理 是我們未來的發展方向。已經掌握了Java、Python、HTML的你,是不是也想了解下最近異?;鸨腉o語言呢?來吧,讓我們一起了解下。
Go 是一個開源的編程語言 ,它能讓構造簡單、可靠且高效的軟件變得容易。
Go是從2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持開發,后來還加入了Ian Lance Taylor, Russ Cox等人,并最終于2009年11月開源,在2012年早些時候發布了Go 1穩定版本?,F在Go的開發已經是完全開放的,并且擁有一個活躍的社區。這三個人都是計算機界的大神,有的參與了C語言的編寫,有的還是數學大神,有的還獲得了計算機最高榮譽-圖靈獎。
接下來說說 Go語言的特色 :
簡潔、快速、安全
并行、有趣、開源
內存管理、數組安全、編譯迅速
Go語言的用途 :
Go 語言被設計成一門應用于搭載 Web 服務器,存儲集群或類似用途的巨型中央服務器的系統編程語言。
對于高性能分布式系統領域而言,Go 語言無疑比大多數其它語言有著更高的開發效率。它提供了海量并行的支持,這對于 游戲 服務端的開發而言是再好不過了。
Go語言的環境安裝:
建議直接打開 官方地址因為墻的原因打不開
因為我用的是windows系統,這里主要講下Windows系統上使用Go語言來編程。
Windows 下可以使用 .msi 后綴(在下載列表中可以找到該文件,如go1.17.2.windows-amd64.msi)的安裝包來安裝。
默認情況下 .msi 文件會安裝在 c:Go 目錄下。你可以將 c:Gobin 目錄添加到 Path 環境變量中。添加后你需要重啟命令窗口才能生效。個人建議還是安裝到 Program Files文件夾中。
使用什么開發工具來對Go語言進行編寫:
個人建議用VS code, 也可以用Sublime Text來編輯。如果你之前看了我講的HTML語言的學習,肯定已經下載了VS code. 那么這時你需要在VS code中下載Go語言的擴展插件。
這里有一個巨大的坑,就是在下載Go的插件和依賴包時,會提示一些包沒有。主要是因為下載的依賴包部分被墻了,只能想別的辦法去下載。
建議參考網頁:
解決vscode中golang插件安裝失敗方法
在學習go的過程中,使用的是vscode,但是一直提示安裝相關插件失敗,然后上網查方法,基本上是叫你建立golang.org目錄什么的,結果全是錯的,而且都是抄襲,很煩。無意之中看到一位博主分享的方法,他也是飽受上述的垃圾博文困擾,然后找到了解決方法,這里向他致敬,秉著讓更多人看到正確解決方法的心,我寫下正確的解決方法,希望對你有所幫助,也可以點開原博主鏈接參考:
Go有一個全球模塊代理,設置代理再去安裝golang的插件,就可以安裝成功了。步驟有,首先Windows用戶打開Powershell,一個藍色的界面,注意不是cmd!不知道的直接打開window下面的搜索,然后輸入powershell,搜索出來就可以了。
$env:GO111MODULE=“on”
$env:GOPROXY=“”
go env -w GOPROXY=
go env -w GOPRIVATE=*.corp.example.com
然后我們打開VsCode界面,下面會提示安裝插件,我們選擇Install ALL,就會安裝成功
當你在運行Go語言程序時,提示所有的插件包都已經安裝成功了時,就可以正常使用了,要不然一堆報錯會讓你非常心煩。
好了,今天先到這里,晚安、下班~
本文名稱:go語言使用zk,go語言使用什么框架
網頁地址:http://vcdvsql.cn/article46/hegjeg.html
成都網站建設公司_創新互聯,為您提供手機網站建設、商城網站、品牌網站設計、移動網站建設、關鍵詞優化、網站排名
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯