Java轉Go日記(三十六):簡單的分布式

1.1.1. 簡單的分布式server

目前分布式系統已經很流行了,一些開源框架也被廣泛應用,如dubbo、Motan等。對于一個分布式服務,最基本的一項功能就是服務的注冊和發現,而利用zk的EPHEMERAL節點則可以很方便的實現該功能。EPHEMERAL節點正如其名,是臨時性的,其生命周期是和客戶端會話綁定的,當會話連接斷開時,節點也會被刪除。下邊我們就來實現一個簡單的分布式server:

server:

服務啟動時,創建zk連接,并在go_servers節點下創建一個新節點,節點名為"ip:port",完成服務注冊 服務結束時,由于連接斷開,創建的節點會被刪除,這樣client就不會連到該節點

client:

先從zk獲取go_servers節點下所有子節點,這樣就拿到了所有注冊的server 從server列表中選中一個節點(這里只是隨機選取,實際服務一般會提供多種策略),創建連接進行通信 這里為了演示,我們每次client連接server,獲取server發送的時間后就斷開。主要代碼如下:

server.go

package mainimport ("fmt""net""os""time""github.com/samuel/go-zookeeper/zk"
)func main() {go starServer("127.0.0.1:8897")go starServer("127.0.0.1:8898")go starServer("127.0.0.1:8899")a := make(chan bool, 1)<-a
}func checkError(err error) {if err != nil {fmt.Println(err)}
}func starServer(port string) {tcpAddr, err := net.ResolveTCPAddr("tcp4", port)fmt.Println(tcpAddr)checkError(err)listener, err := net.ListenTCP("tcp", tcpAddr)checkError(err)//注冊zk節點q// 鏈接zkconn, err := GetConnect()if err != nil {fmt.Printf(" connect zk error: %s ", err)}defer conn.Close()// zk節點注冊err = RegistServer(conn, port)if err != nil {fmt.Printf(" regist node error: %s ", err)}for {conn, err := listener.Accept()if err != nil {fmt.Fprintf(os.Stderr, "Error: %s", err)continue}go handleCient(conn, port)}fmt.Println("aaaaaa")
}func handleCient(conn net.Conn, port string) {defer conn.Close()daytime := time.Now().String()conn.Write([]byte(port + ": " + daytime))
}
func GetConnect() (conn *zk.Conn, err error) {zkList := []string{"localhost:2181"}conn, _, err = zk.Connect(zkList, 10*time.Second)if err != nil {fmt.Println(err)}return
}func RegistServer(conn *zk.Conn, host string) (err error) {_, err = conn.Create("/go_servers/"+host, nil, zk.FlagEphemeral, zk.WorldACL(zk.PermAll))return
}func GetServerList(conn *zk.Conn) (list []string, err error) {list, _, err = conn.Children("/go_servers")return
}

1.1.2. client.go

package mainimport ("errors""fmt""io/ioutil""math/rand""net""time""github.com/samuel/go-zookeeper/zk"
)func checkError(err error) {if err != nil {fmt.Println(err)}
}
func main() {for i := 0; i < 100; i++ {startClient()time.Sleep(1 * time.Second)}
}func startClient() {// service := "127.0.0.1:8899"//獲取地址serverHost, err := getServerHost()if err != nil {fmt.Printf("get server host fail: %s \n", err)return}fmt.Println("connect host: " + serverHost)tcpAddr, err := net.ResolveTCPAddr("tcp4", serverHost)checkError(err)conn, err := net.DialTCP("tcp", nil, tcpAddr)checkError(err)defer conn.Close()_, err = conn.Write([]byte("timestamp"))checkError(err)result, err := ioutil.ReadAll(conn)checkError(err)fmt.Println(string(result))return
}func getServerHost() (host string, err error) {conn, err := GetConnect()if err != nil {fmt.Printf(" connect zk error: %s \n ", err)return}defer conn.Close()serverList, err := GetServerList(conn)if err != nil {fmt.Printf(" get server list error: %s \n", err)return}count := len(serverList)if count == 0 {err = errors.New("server list is empty \n")return}//隨機選中一個返回r := rand.New(rand.NewSource(time.Now().UnixNano()))host = serverList[r.Intn(3)]return
}
func GetConnect() (conn *zk.Conn, err error) {zkList := []string{"localhost:2181"}conn, _, err = zk.Connect(zkList, 10*time.Second)if err != nil {fmt.Println(err)}return
}
func GetServerList(conn *zk.Conn) (list []string, err error) {list, _, err = conn.Children("/go_servers")return
}

先啟動server,可以看到有三個節點注冊到zk:

    127.0.0.1:8897127.0.0.1:8899127.0.0.1:88982018/08/27 14:04:58 Connected to 127.0.0.1:21812018/08/27 14:04:58 Connected to 127.0.0.1:21812018/08/27 14:04:58 Connected to 127.0.0.1:21812018/08/27 14:04:58 Authenticated: id=100619932030205976, timeout=100002018/08/27 14:04:58 Re-submitting `0` credentials after reconnect2018/08/27 14:04:58 Authenticated: id=100619932030205977, timeout=100002018/08/27 14:04:58 Re-submitting `0` credentials after reconnect2018/08/27 14:04:58 Authenticated: id=100619932030205978, timeout=100002018/08/27 14:04:58 Re-submitting `0` credentials after reconnect

啟動client,可以看到每次client都會隨機連接到一個節點進行通信:

    2018/08/27 14:05:21 Connected to 127.0.0.1:21812018/08/27 14:05:21 Authenticated: id=100619932030205979, timeout=100002018/08/27 14:05:21 Re-submitting `0` credentials after reconnect2018/08/27 14:05:21 Recv loop terminated: err=EOFconnect host: 127.0.0.1:88992018/08/27 14:05:21 Send loop terminated: err=<nil>read tcp 127.0.0.1:54062->127.0.0.1:8899: read: connection reset by peer127.0.0.1:8899: 2018-08-27 14:05:21.291641 +0800 CST m=+22.4801496562018/08/27 14:05:22 Connected to [::1]:21812018/08/27 14:05:22 Authenticated: id=100619932030205980, timeout=100002018/08/27 14:05:22 Re-submitting `0` credentials after reconnect2018/08/27 14:05:22 Recv loop terminated: err=EOF2018/08/27 14:05:22 Send loop terminated: err=<nil>connect host: 127.0.0.1:8897read tcp 127.0.0.1:54064->127.0.0.1:8897: read: connection reset by peer127.0.0.1:8897: 2018-08-27 14:05:22.302322 +0800 CST m=+23.4908013852018/08/27 14:05:23 Connected to 127.0.0.1:21812018/08/27 14:05:23 Authenticated: id=100619932030205981, timeout=100002018/08/27 14:05:23 Re-submitting `0` credentials after reconnect2018/08/27 14:05:23 Recv loop terminated: err=EOF2018/08/27 14:05:23 Send loop terminated: err=<nil>connect host: 127.0.0.1:8897read tcp 127.0.0.1:54070->127.0.0.1:8897: read: connection reset by peer127.0.0.1:8897: 2018-08-27 14:05:23.312873 +0800 CST m=+24.5013242282018/08/27 14:05:24 Connected to 127.0.0.1:21812018/08/27 14:05:24 Authenticated: id=100619932030205982, timeout=100002018/08/27 14:05:24 Re-submitting `0` credentials after reconnect2018/08/27 14:05:24 Recv loop terminated: err=EOFconnect host: 127.0.0.1:88992018/08/27 14:05:24 Send loop terminated: err=<nil>read tcp 127.0.0.1:54072->127.0.0.1:8899: read: connection reset by peer127.0.0.1:8899: 2018-08-27 14:05:24.323668 +0800 CST m=+25.5120901552018/08/27 14:05:25 Connected to 127.0.0.1:21812018/08/27 14:05:25 Authenticated: id=100619932030205983, timeout=100002018/08/27 14:05:25 Re-submitting `0` credentials after reconnect2018/08/27 14:05:25 Recv loop terminated: err=EOF2018/08/27 14:05:25 Send loop terminated: err=<nil>connect host: 127.0.0.1:8897read tcp 127.0.0.1:54074->127.0.0.1:8897: read: connection reset by peer127.0.0.1:8897: 2018-08-27 14:05:25.330257 +0800 CST m=+26.5186505662018/08/27 14:05:26 Connected to [::1]:21812018/08/27 14:05:26 Authenticated: id=100619932030205984, timeout=100002018/08/27 14:05:26 Re-submitting `0` credentials after reconnect2018/08/27 14:05:26 Recv loop terminated: err=EOF2018/08/27 14:05:26 Send loop terminated: err=<nil>connect host: 127.0.0.1:8897read tcp 127.0.0.1:54080->127.0.0.1:8897: read: connection reset by peer127.0.0.1:8897: 2018-08-27 14:05:26.357251 +0800 CST m=+27.5456146162018/08/27 14:05:27 Connected to 127.0.0.1:21812018/08/27 14:05:27 Authenticated: id=100619932030205985, timeout=100002018/08/27 14:05:27 Re-submitting `0` credentials after reconnectconnect host: 127.0.0.1:88992018/08/27 14:05:27 Recv loop terminated: err=EOF2018/08/27 14:05:27 Send loop terminated: err=<nil>read tcp 127.0.0.1:54082->127.0.0.1:8899: read: connection reset by peer127.0.0.1:8899: 2018-08-27 14:05:27.369096 +0800 CST m=+28.5574307642018/08/27 14:05:28 Connected to [::1]:21812018/08/27 14:05:28 Authenticated: id=100619932030205986, timeout=100002018/08/27 14:05:28 Re-submitting `0` credentials after reconnect2018/08/27 14:05:28 Recv loop terminated: err=EOF2018/08/27 14:05:28 Send loop terminated: err=<nil>connect host: 127.0.0.1:8898read tcp 127.0.0.1:54084->127.0.0.1:8898: read: connection reset by peer127.0.0.1:8898: 2018-08-27 14:05:28.380455 +0800 CST m=+29.568760988......

至此,我們的分布式server就實現了

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/80989.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/80989.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/80989.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

機器學習筆記——特征工程

大家好&#xff0c;這里是好評筆記&#xff0c;公主號&#xff1a;Goodnote&#xff0c;專欄文章私信限時Free。本筆記介紹機器學習中常見的特征工程方法、正則化方法和簡要介紹強化學習。 文章目錄 特征工程&#xff08;Fzeature Engineering&#xff09;1. 特征提取&#xff…

在 Ubuntu 20.04.6 LTS 中將 SCons 從 3.1.2 升級到 4.9.1

在 Ubuntu 20.04.6 LTS 中將 SCons 從 3.1.2 升級到 4.9.1&#xff0c;可以通過以下步驟完成&#xff1a; 方法 1&#xff1a;使用 pip 安裝&#xff08;推薦&#xff09; 步驟 1&#xff1a;卸載舊版本 SCons # 如果通過 apt 安裝的舊版本&#xff0c;先卸載 sudo apt remov…

LeetCode熱題100--234.回文鏈表--簡單

1. 題目 給你一個單鏈表的頭節點 head &#xff0c;請你判斷該鏈表是否為回文鏈表。如果是&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 示例 1&#xff1a; 輸入&#xff1a;head [1,2,2,1] 輸出&#xff1a;true 示例 2&#xff1a; 輸入&#xf…

【markdown】介紹如何在markdown中繪制流程圖

在 Markdown 中編寫流程圖主要通過 ??Mermaid 語法??實現&#xff08;多數平臺如 GitHub、VS Code、Typora 已原生支持&#xff09;。以下是詳細方法&#xff1a; 1. 基礎流程圖?? 語法結構 用 mermaid 包裹代碼塊&#xff0c;指定方向后定義節點和連接線&#xff1a…

Java中使用自定義序列化器:自動添加View字段的實現與應用

Java 中 BigDecimal 序列化器:自動添加 View 返回字段的實現與應用 在 Java 開發過程中,數據的序列化與反序列化是非常重要的環節。當我們處理數值類型數據,特別是BigDecimal類型時,有時需要在序列化輸出中添加額外的視圖字段,以滿足前端展示或者特定業務需求。本文將通過…

Java類一文分解:JavaBean,工具類,測試類的深度剖析

解鎖Java類的神秘面紗&#xff1a;從JavaBean到測試類的深度剖析 前言一、JavaBean 類&#xff1a;數據的守護者&#xff08;一&#xff09;JavaBean 類是什么&#xff08;二&#xff09;JavaBean 類的特征&#xff08;三&#xff09;JavaBean 類的使用場景&#xff08;四&…

機器學習-- 線性回歸、邏輯回歸

線性回歸 線性回歸是一種統計方法,用于發現變量之間的關系。在機器學習背景下,線性回歸可找出特征(Feature)與標簽(Lable)之間的關系。 例如,假設我們想要根據汽車的重量預測汽車的每加侖汽油行駛里程(mpg),并且我們有以下數據集: 線性回歸方程 Linear regressi…

Lua再學習

因為實習的項目用到了Lua&#xff0c;所以再來深入學習一下 函數 函數的的多返回值 Lua中的函數可以實現多返回值&#xff0c;實現方法是再return后列出要返回的值的列表&#xff0c;返回值也可以通過變量接收到&#xff0c;變量不夠也不會影響接收對應位置的返回值 Lua中傳…

TCP協議十大核心特性深度解析:構建可靠傳輸的基石

TCP&#xff08;傳輸控制協議&#xff09;作為互聯網的"交通指揮官"&#xff0c;承載著全球80%以上的網絡流量。本文將深入解析TCP協議的十大核心特性&#xff0c;通過原理剖析、流程圖解和實戰案例&#xff0c;揭示其如何實現高效可靠的數據傳輸。 一、面向連接的可…

基于 Spring Boot 瑞吉外賣系統開發(十三)

基于 Spring Boot 瑞吉外賣系統開發&#xff08;十三&#xff09; 查詢套餐 在查詢套餐信息時包含套餐的分類名&#xff0c;分類名稱在category表中&#xff0c;因此這里需要進行兩表關聯查詢。 自定義SQL如下&#xff1a; select s.* ,c.name as category_name from setmeal…

華為IP(6)

VLAN聚合 VLAN聚合產生的技術背景 在一般是三層交換機中&#xff0c;通常采用一個VLAN接口的方式實現廣播域之間的互通&#xff0c;這在某些情況下導致了IP地址的浪費 因為一個VLAN對應的子網中&#xff0c;子網號、子網廣播地址、子網網關地址不能用作VLAN內的主機IP地址&a…

深度解析IP靜態的工作原理,IP靜態的應用場景又哪些?

一、什么是IP靜態&#xff1f; 當我們談到“IP靜態”時&#xff0c;大家可能首先想到的是與“動態IP”相對的概念。確實如此&#xff0c;靜態IP是一種固定分配的IP地址&#xff0c;也就是說&#xff0c;在特定時間內&#xff0c;分配給你的IP地址不會有所更改——無論你完成多…

docker(四)使用篇一:docker 鏡像倉庫

前文我們已經介紹了 docker 并安裝了 docker&#xff0c;下面我們將正式步入使用環節&#xff0c;本章是第一個使用教學&#xff1a;docker 鏡像倉庫。 一、什么是鏡像倉庫 所謂鏡像倉庫&#xff0c;其實就是負責存儲、管理和分發鏡像的倉庫&#xff0c;并且建立了倉庫的索引…

單片機開發軟件

目錄 純編碼 vscode Ardunio Keil 1. 集成化開發環境&#xff08;IDE&#xff09; 2. 多架構芯片支持 3. 高效的代碼生成與優化 4. 強大的調試與仿真功能 5. 豐富的庫函數與生態系統 6. 教育與企業級適用性 典型應用場景 半編碼半圖形化 STM32CUBEIED 1. 圖形化配置…

【虛幻引擎】UE5獨立游戲開發全流程(商業級架構)

本套課程我將會講解一下知識 1.虛幻引擎的常用功能節點、模塊包含但不限于動畫模塊、UI模塊、AI模塊、碰撞模塊、傷害模塊、背包模塊、準心模塊、武器模塊、可拾取物品模塊、死亡等模塊。 2.整個游戲的設計思路&#xff08;游戲架構&#xff09;&#xff0c;本套教程講解了如…

ABP-Book Store Application中文講解 - Part 2: The Book List Page

本章用于介紹如何創建Book List Page。 TBD 1. 匯總 ABP-Book Store Application中文講解-匯總-CSDN博客 2. 前一章 ABP-Book Store Application中文講解 - Part 1: Creating the Server Side 項目之間的引用關系。 目錄 1. 多語言配置 1.1 zh-Hans.json 1.2 en.jso…

6、登錄功能后端開發

6、登錄功能后端開發 https://xiaoxueblog.com/ai/%E7%99%BB%E5%BD%95%E5%8A%9F%E8%83%BD%E5%90%8E%E7%AB%AF%E5%BC%80%E5%8F%91.html 1、新建用戶表SQL腳本 -- CREATE DATABASE aicloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;-- 創建用戶表 drop table if exi…

隨機矩陣放大的方式 生成相位數據集,用于相位展開

import os import numpy as np import matplotlib.pyplot as plt from scipy.ndimage import zoom import gc from tqdm import tqdm from zernike import RZerndef wrap_phase(phase):"""將相位包裹到[-π, π]區間"""return np.angle(np.exp(1…

Java面試全記錄:Spring Cloud+Kafka+Redis實戰解析

Java面試全記錄&#xff1a;Spring CloudKafkaRedis實戰解析 人物設定 姓名&#xff1a;張偉&#xff08;隨機生成唯一姓名&#xff09; 年齡&#xff1a;28歲 學歷&#xff1a;碩士 工作年限&#xff1a;5年 工作內容&#xff1a; 基于Spring Cloud搭建微服務架構使用Kafka…

Java Socket編程完全指南:從基礎到實戰應用

Socket編程是構建網絡應用的基石&#xff0c;Java通過java.net包提供了強大的Socket API。本文將深入解析Java Socket類的核心用法&#xff0c;涵蓋TCP/UDP協議實現、多線程通信及性能優化技巧&#xff0c;助您快速掌握網絡編程精髓。 一、Socket編程核心概念 1.1 網絡通信模型…