88.go微服务之RPC实践

微服务是现在大多数新项目会采用的架构。服务端提供服务,客户端调用服务端的功能,就像调用一个函数一样。微服务的更新升级,只要接口没有变化,客户端完全可以无影响地升级到新功能。这就是微服务的第一个体验。
随之而来的,就是每个微服务都可以用任意计算机语言实现,方便了不同技术团队的协作。
而整个软件系统的构成,也不同于以往的实现方式了。这样的构成,更灵活和强大。当然随着服务数量的增加,也增加了服务的管理难度。
go语言的RPC服务实现起来非常简单。可以利用tcp或http协议来传递数据。
我们通过一个计算矩形面积和周长的微服务实例来学习rpc服务的编写方法。
首先,实现server端(server.go),定义一个矩形

//  声明矩形结构体
type Rect struct {

}

再定义矩形的参数

//  声明参数结构体
type Params struct {
    //  宽,高
    Width, Height int
}

因为计算面积和周长的RPC服务是远程调用,那么在服务端计算,通过获取和改变内存变量的值实现调用远程微服务像本地函数一样的效果。所以,传入的参数除了宽和高以外,还有一个供承载计算结果的整形指针。如果发生错误,就返回error,无错误的时候,return nil 就可以了。

//  计算矩形面积
func (r *Rect) Area(p Params, ret *int) error {
    *ret = p.Width * p.Height
    return nil
}
//  计算周长
func (r *Rect) Perimeter(p Params, ret *int) error {
    *ret = (p.Width + p.Height) * 2
    return nil
}

在主函数中,首先要注册服务

    //  注册服务
    rect := new(Rect)
    rpc.Register(rect)

然后绑定服务到http协议

// 服务绑定http协议
    rpc.HandleHTTP()

最后服务器开始监听服务,等待客户端来调用。这个服务我们使用8080端口。

//  监听服务,等待客户端调用(求面积和周长的方法)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal(err)
    }

至此,微服务server端代码已经写完。
下面开始编写微服务client端代码(client.go)。
client端要和server端拥有相同的参数结构体。即

//  参数
type Params struct {
    Width, Height int
}

client远程连接server,这里采用tcp协议,还需要提前知道server的地址和通讯端口。以下代码建立远程连接,并得到一个实例rp。

//  连接远程的RPC服务
    rp, err := rpc.DialHTTP("tcp", "127.0.0.1:8080")
    if err != nil {
        log.Println(err)
    }

为了获取计算结果和提供计算参数,声明2个变量。一个保存结果,一个保存参数。

    //  结果
    ret := 0
    //  参数
    p := Params{50 ,100}

调用远程服务(面积)

//  1. 求面积
    err2 := rp.Call("Rect.Area", p, &ret)
    if err2 != nil {
        log.Println(err2)
    }else{
        fmt.Println("面积:", ret)
    }

调用远程服务(周长)

//  2. 求周长
    err3 := rp.Call("Rect.Perimeter", p, &ret)
    if err3 != nil {
        log.Println(err3)
    }else {
        fmt.Println("周长:", ret)
    }

运行客户端client.go,由于此时server未启动,所以客户端会得到一个连接被拒绝的结果。

2021/03/21 20:23:48 dial tcp 127.0.0.1:8080: connectex: 由于目标计算机积极拒绝,无法连接。
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x10 pc=0x109e944]
...

启动server端,再次运行client端,得到运行结果

面积: 5000
周长: 300

server.go 完整代码

/**
* Package: rpcServer
* Description: This package is rpcServer example
* Author: Jian Junbo
* Email: junbojian@qq.com
* Date:  2021/3/21 17:31
* Copyright ©2021 Jian Junbo & Shanxi Xiyue Mancang Technology Co., Ltd. All rights reserved.
**/
package main

import (
    "log"
    "net/http"
    "net/rpc"
)

//  声明矩形结构体
type Rect struct {

}
//  声明参数结构体
type Params struct {
    //  宽,高
    Width, Height int
}
//  计算矩形面积
func (r *Rect) Area(p Params, ret *int) error {
    *ret = p.Width * p.Height
    return nil
}
//  计算周长
func (r *Rect) Perimeter(p Params, ret *int) error {
    *ret = (p.Width + p.Height) * 2
    return nil
}

func main() {
    //  注册服务
    rect := new(Rect)
    rpc.Register(rect)
    // 服务绑定http协议
    rpc.HandleHTTP()
    //  监听服务,等待客户端调用(求面积和周长的方法)
    err := http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal(err)
    }
}

client.go 完整代码

/**
* Package: rpcClient
* Description: This package is rpcClient example.
* Author: Jian Junbo
* Email: junbojian@qq.com
* Date:  2021/3/21 18:31
* Copyright ©2021 Jian Junbo & Shanxi Xiyue Mancang Technology Co., Ltd. All rights reserved.
**/
package main

import (
    "fmt"
    "log"
    "net/rpc"
)
//  参数
type Params struct {
    Width, Height int
}

//  主函数调用服务
func main() {
    //  连接远程的RPC服务
    rp, err := rpc.DialHTTP("tcp", "127.0.0.1:8080")
    if err != nil {
        log.Println(err)
    }
    //  * 调用服务方法
    //  结果
    ret := 0
    //  参数
    p := Params{50 ,100}
    //  1. 求面积
    err2 := rp.Call("Rect.Area", p, &ret)
    if err2 != nil {
        log.Println(err2)
    }else{
        fmt.Println("面积:", ret)
    }

    //  2. 求周长
    err3 := rp.Call("Rect.Perimeter", p, &ret)
    if err3 != nil {
        log.Println(err3)
    }else {
        fmt.Println("周长:", ret)
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容