微服務中很重要的一個內容就是「RPC」遠程過程調用(Remote Procedure Call,縮寫為 RPC)是一個計算機通信協議,他的主要作用是「允許運行于一臺計算機的程序調用另一臺計算機的子程序,而程序員無需額外地為這個交互作用編程」。


引言?
"微服務"這個概念想必不用我說大家都知道,就算沒接觸過也聽說過。簡單來說就是以前系統中的,用戶,搜索,內容,等等模塊都在一起,這樣會導致代碼「越來越冗余,越來越難維護」,所以往往需要拆分這些服務,微服務在拆分的時候,會根據業務功能模塊把一個單體的應用拆分成許多個獨立的項目,每個項目完成一部分的業務功能,然后獨立開發和部署。這些獨立的項目就成為一個微服務。進而構成一個「服務集群」??聪旅鎯蓮垐D可能會對微服務的概念更加直觀。
單體服務

單體服務
微服務

微服務
RPC介紹?
微服務中很重要的一個內容就是「RPC」遠程過程調用(Remote Procedure Call,縮寫為 RPC)是一個計算機通信協議,他的主要作用是「允許運行于一臺計算機的程序調用另一臺計算機的子程序,而程序員無需額外地為這個交互作用編程」。
那么RPC是如何實現的呢?今天咱們就以golang為工具,給大家實現一個簡單的用rpc輸出helloWorld。
RPC實現步驟?
其實RPC的實現和網絡編程有點像,A服務需要遠程調用B服務的某個方法,在這種情況下我們就把B服務稱為「服務端」,A稱為「客戶端」。

具體實現步驟如下圖:
RPC實現步驟
服務端?
1、注冊服務對象,綁定類方法
rpc.ResisterName("服務名","回調對象")
ResisterName函數解釋
func RegisterName(name string, rcvr interface{}) error
//參數解釋
//name 服務名(自己隨便取),字符串類型
//rcvr 對應的RPC對象,該對象綁定的方法需要滿足如下條件
1)方法必須是導出的(包外可見),在golang中的體現為,方法名首字母大寫
2)方法必須有兩個參數,都是導出類型,內建類型
3) 方法的第二個參數(也就是客戶端調用遠程函數中的傳出參數),必須指針(傳出參數)
4) 該方法只有一個返回值,就是error接口類型的返回值
下面我們針對參數2舉個例子,比如下面這個方法TestMethod 就是符合條件的。type Test struct{
}
//這是符合RegisterName的參數2的方法名
func (this *Test) TestMethod(name string, resp *string)error{
return nil
}
rpc.RegisterName("test", new(Test)) //注冊rpc服務對象
2、創建監聽器
listener, err := net.Listen()
3、啟動監聽,建立鏈接
conn, err := listener.Accept()
4、將鏈接綁定RPC服務
ServerConn函數解釋
func (server *Server) ServeConn(conn io.ReadWriteCloser)
//參數conn為成功建立好連接的socket,也就是前面的conn
客戶端?
1、用RPC連接服務器(服務端)
2、調用遠程函數
conn.Call("服務名.方法名", "傳入參數", "傳出參數")
func (client *Client) Call(serviceMethod string, args interface{}, reply interface{}) error
//參數含義
//serviceMethod "服務名"."方法名"
//args "傳入參數" 調用方法需要的參數
//reply "傳出參數" 定義一個變量,對變量名取地址 &變量,完成傳參
代碼示例?
服務端代碼?
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
}
//設置監聽
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)
}