drpc功能设计图
https://blog.csdn.net/chen802311/article/details/103534785
drpc部署
-
drpc实现为可以单机或者多机分布式部署
-
单机部署例子:
drpcd.exe -addr=:8080
启动了一个监听8080端口的drpcd服务,其他的各种运用程序可以把自己实现的功能注册上去,也可以方便的调用其他运用程序注册的函数功能,实现功能共享。
-
多机部署例子:
drpcd.exe -addr=192.168.1.11:8080 // 启动第一个drpcd服务
drpcd.exe -addr=192.168.1.12:8080 -peer=192.168.1.11:8080 // 加入到IP 11机器的drpcd服务群
drpcd.exe -addr=192.168.1.13:8080 -peer=192.168.1.12:8080 // 加入到IP 12机器的drpcd服务群
...
此时这些drpcd服务会相互连接为一个连通无环图, 比如有程序在IP 11机器上注册了函数 foo ,此时另外的程序可以连接IP 13机器调用foo函数(即使foo函数没有被直接注册到IP 13的机器上) 所有被注册的功能函数在drpcd服务群中是共享的。
-
浏览器访问: ip:port/drpcd/methodsdoc 可以看到当前drpcd群中所有注册的函数与使用说明(由于对html不熟,目前直接返回json给浏览器,格式很丑陋,之后会使用html展示)
-
浏览器访问: ip:port/drpcd/clusteraddrs 可以看到当前drpcd群中所有drpcd的网络地址
注意:
1:单台电脑上测试多机部署,可以用相同的ip 不同的绑定端口测试
2:单机部署的addr命令行参数可以只写端口不写IP, 多机部署必须写完整的IP与端口
开发
- go get github.com/button-chen/drpc/...
- golang版本大于等于 1.13.5
Example
运用程序注册功能到平台:
package main
import (
"crypto/hmac"
"crypto/md5"
"encoding/hex"
"flag"
"log"
"os"
"os/signal"
"github.com/button-chen/drpc"
)
func myHMACMD5(data, key []byte) string {
hmac := hmac.New(md5.New, key)
hmac.Write(data)
return hex.EncodeToString(hmac.Sum(nil))
}
var myHMACMD5Doc = `
函数名:myHMACMD5
功能: 计算hmac-md5
参数(json):
{
"data":"", // hmac-md5需要加密的字符串
"key":"" // hmac-md5需要的key
}
返回值(json):
{
"result":""
}
`
var (
addr = flag.String("addr", "127.0.0.1:8080", "address")
name = flag.String("reg", "myHMACMD5", "address")
)
func main() {
flag.Parse()
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
rpcclient := drpc.NewDRPCClient()
rpcclient.ConnectToDRPC(*addr)
type pst struct {
Data string `json:"data"`
Key string `json:"key"`
}
type rst struct {
Result string `json:"result"`
}
err := rpcclient.Register(*name, myHMACMD5Doc, myHMACMD5, (*pst)(nil), (*rst)(nil))
if err == nil {
log.Println("注册成功")
} else {
log.Println("注册失败: ", err)
}
<-interrupt
}
运用程序调用平台中被注册的功能, 方法一:
post 方式访问:http:
参数(json):
{
"FuncName": "foo",
"Timeout": 1000,
"Body": ""
}
返回值(json):
{
"ErrCode": 1,
"Body": ""
}
返回值中错误代码:
1:成功 2:参数格式错误 3:请求超时 4:函数不存在
注:http方式的客户端只支持调用共享功能,而且只能是同步调用,不支持注册功能。
运用程序调用平台中被注册的功能, 方法二:
package main
import (
"encoding/json"
"flag"
"log"
"os"
"os/signal"
"time"
"github.com/button-chen/drpc"
)
var (
addr = flag.String("addr", "127.0.0.1:8080", "address")
name = flag.String("call", "myHMACMD5", "function name")
)
func main() {
flag.Parse()
interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)
rpcclient := drpc.NewDRPCClient()
err := rpcclient.ConnectToDRPC(*addr)
if err != nil {
log.Println(err.Error())
return
}
param := struct {
Key string `json:"key"`
Data string `json:"data"`
}{
"123",
"mydata",
}
t, _ := json.Marshal(param)
ret, err := rpcclient.Call(*name, t, 2000)
tmp := struct {
Result string `json:"result"`
}{}
if err != nil {
log.Println("err:", err.Error())
} else {
json.Unmarshal(ret, &tmp)
log.Println("result:", tmp.Result)
}
fn := func(id int64, msg []byte, err error) {
if err != nil {
log.Println("err: ", err.Error())
} else {
json.Unmarshal(ret, &tmp)
log.Println("return async: ", tmp.Result)
}
}
for {
id := rpcclient.AsyncCall(*name, t, 2000, fn)
_ = id
time.Sleep(time.Millisecond * 10)
}
<-interrupt
}
注: 使用专用客户端库,即可以调用共享功能也可以注册共享功能,而且支持同步与异步调用。