引言
"微服務"這個概念想必不用我說大家都知道,就算沒接觸過也聽說過眠副。簡單來說就是以前系統(tǒng)中的画切,用戶,搜索囱怕,內容霍弹,等等模塊都在一起毫别,這樣會導致代碼越來越冗余,越來越難維護典格,所以往往需要拆分這些服務岛宦,微服務在拆分的時候,會根據(jù)業(yè)務功能模塊把一個單體的應用拆分成許多個獨立的項目耍缴,每個項目完成一部分的業(yè)務功能恋博,然后獨立開發(fā)和部署。這些獨立的項目就成為一個微服務私恬。進而構成一個服務集群×段猓看下面兩張圖可能會對微服務的概念更加直觀
單體服務
微服務
RPC介紹
微服務中很重要的一個內容就是RPC
遠程過程調用(Remote Procedure Call本鸣,縮寫為 RPC)是一個計算機通信協(xié)議,他的主要作用是允許運行于一臺計算機的程序調用另一臺計算機的子程序硅蹦,而程序員無需額外地為這個交互作用編程
那么RPC是如何實現(xiàn)的呢荣德?今天咱們就以golang為工具,給大家實現(xiàn)一個簡單的用rpc輸出helloWorld
RPC實現(xiàn)步驟
其實RPC的實現(xiàn)和網(wǎng)絡編程有點像童芹,A服務需要遠程調用B服務的某個方法涮瞻,在這種情況下我們就把B服務稱為服務端,A稱為客戶端
具體實現(xiàn)步驟如下圖:
服務端
注冊服務對象假褪,綁定類方法(定義類署咽,綁定類方法)
rpc.ResisterName("服務名","回調對象")
ResisterName函數(shù)解釋
func RegisterName(name string, rcvr interface{}) error
//參數(shù)解釋
//name 服務名(自己隨便取),字符串類型
//rcvr 對應的RPC對象生音,該對象綁定的方法需要滿足如下條件
1)方法必須是導出的(包外可見)宁否,在golang中的體現(xiàn)為,方法名首字母大寫
2)方法必須有兩個參數(shù)缀遍,都是導出類型慕匠,內建類型
3) 方法的第二個參數(shù)(也就是客戶端調用遠程函數(shù)中的傳出參數(shù)),必須指針(傳出參數(shù))
4) 該方法只有一個返回值域醇,就是error接口類型的返回值
下面我們針對參數(shù)2舉個例子,比如下面這個方法TestMethod 就是符合條件的
type Test struct{
}
//這是符合RegisterName的參數(shù)2的方法名
func (this *Test) TestMethod(name string, resp *string)error{
return nil
}
rpc.RegisterName("test", new(Test)) //注冊rpc服務對象
創(chuàng)建監(jiān)聽器
listener, err := net.Listen()
啟動監(jiān)聽台谊,建立鏈接
conn, err := listener.Accept()
將鏈接綁定RPC服務
rpc.ServerConn(conn)
ServerConn函數(shù)解釋
func (server *Server) ServeConn(conn io.ReadWriteCloser)
//參數(shù)conn為成功建立好連接的socket,也就是前面的conn
客戶端
用RPC連接服務器(服務端)
conn, err := rpc.Dail()
調用遠程函數(shù)
conn.Call("服務名.方法名", "傳入?yún)?shù)", "傳出參數(shù)")
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
//參數(shù)含義
//serviceMethod "服務名"."方法名"
//args "傳入?yún)?shù)" 調用方法需要的參數(shù)
//reply "傳出參數(shù)" 定義一個變量譬挚,對變量名取地址 &變量锅铅,完成傳參
代碼示例
服務端代碼
server.go
package main
import (
"fmt"
"net"
"net/rpc"
)
type Hello struct {
}
func (this *Hello) HelloWorld(name string, resp *string) (err error) {
*resp = name + "您好!"
return err
}
func main() {
//注冊rpc服務殴瘦,指定對象和方法
err := rpc.RegisterName("hello", new(Hello))
if err != nil {
fmt.Println("注冊 err:", err)
return
}
//設置監(jiān)聽
listener, err := net.Listen("tcp", "127.0.0.1:8088")
if err != nil {
fmt.Println("listen err:", err)
return
}
defer listener.Close()
//建立連接
conn, err := listener.Accept()
if err != nil {
fmt.Println("accept err:", err)
return
}
defer conn.Close()
//綁定服務
rpc.ServeConn(conn)
}
客戶端代碼
client.go
package main
import (
"fmt"
"net/rpc"
)
func main() {
//用rpc鏈接服務器
conn, err := rpc.Dial("tcp", "127.0.0.1:8088")
if err != nil {
fmt.Println("Dial err:", err)
return
}
defer conn.Close()
var resp *string
conn.Call("hello.HelloWorld", "小飯", &resp)
fmt.Println(*resp)
}
本文由mdnice多平臺發(fā)布