RPC(Remote Procedure Call)远程方法调用,独立于主进程,崩溃不影响主进程
涉及服务端和客户端,服务端及被调用的方法
服务端
package main
import (
"fmt"
"log"
"net/http"
"net/rpc"
"netvine.com/webServer/cgo/magic"
"netvine.com/webServer/cgo/virus"
)
func main() {
//register object as a service
fmt.Println("启动webServer")
MagicService := new(magic.MagicService)
//VirusService := new(virus.VirusService)
err1 := rpc.Register(MagicService) //注册service
//err2 := rpc.Register(VirusService)
if err1 != nil {
log.Fatalf("Format of service MagicService isn't correct. %s", err1)
}
//if err2 != nil {
// log.Fatalf("Format of service VirusService isn't correct. %s", err2)
//}
rpc.HandleHTTP() //注册 HTTP 路由
//start listening for messages on port 4220
//在端口1234上启动一个 HTTP 服务,请求 rpc 方法交给rpc内部路由处理
if err := http.ListenAndServe(":4220", nil); err != nil {
log.Fatalf("Couldn't start listening on port 4220. Error %s", err)
}
log.Println("Serving RPC handler")
}
服务端具体实现方法
//go:build linux
// +build linux
package magic
import (
"fmt"
"github.com/rakyll/magicmime"
"time"
)
type MagicService struct {
}
type MagicReq string
type MagicResp string
func (t *MagicService) InitMagic(file MagicReq, resp *MagicResp) error {
*resp = MagicResp("初始化文件检测InitMagic " + time.Now().Local().Format("2006-01-02 15:04:05"))
if err := magicmime.Open(magicmime.MAGIC_MIME_TYPE | magicmime.MAGIC_SYMLINK | magicmime.MAGIC_ERROR); err != nil {
return err
}
fmt.Println("初始化文件检测InitMagic" + time.Now().Local().Format("2006-01-02 15:04:05"))
return nil
}
func (t *MagicService) UnInitMagic() {
magicmime.Close()
}
// GetFileType 获取文件类型
// 需要头文件: #include <magic.h>
// 返回值: image/jpeg
// rpc库对注册的方法有一定的限制,方法必须满足func (t *T) MethodName(argType T1, replyType *T2) error{}
func (t *MagicService) GetFileType(file string, resp *MagicResp) error {
defer func() {
if err := recover(); err != nil {
fmt.Println("文件类型检测捕获异常", err)
}
}()
res, err := magicmime.TypeByFile(file)
*resp = MagicResp(res)
if err != nil {
fmt.Println("获取文件类型失败,文件路径为:" + file + time.Now().Local().Format("2006-01-02 15:04:05"))
return err
}
fmt.Println("返回值是", string(*resp))
return nil
}
客户端直接调用约定好的端口
rpc.DialHTTP("tcp", ":1234")
连接到服务端的监听地址,返回一个 rpc 的客户端对象
package global
import (
"net/rpc"
"go.uber.org/zap"
"netvine.com/webServer/cgo/magic"
"netvine.com/webServer/cgo/virus"
)
// make connection to rpc server
var Client *rpc.Client
func InitClient() {
var err error
Client, err = rpc.DialHTTP("tcp", ":4220")
if err != nil {
NETVINE_LOG.Error("Error in dialing. %s", zap.Error(err))
return
}
//make arguments object
//var virusResp virus.VirusResp
var magicResp magic.MagicResp
//初始化文件检测
err = Client.Call("MagicService.InitMagic", "", &magicResp)
//初始化病毒库
//err = Client.Call("VirusService.InitVirusEngine", NETVINE_CONFIG.FileDetection.VirusPath, &virusResp)
if err != nil {
NETVINE_LOG.Error("Error in dialing. %s", zap.Error(err))
}
NETVINE_LOG.Info("初始化文件检测&病毒库")
// //call remote procedure with args
// //病毒库
// str := "2.jpg"
// path := "/data/logs/fw-engine/filestore/"
// err = Client.Call("MagicService.GetFileType", path+str, &magicResp)
// //文件检测
// str2 := "2.jpg"
// err = Client.Call("VirusService.FindVirus", path+str2, &virusResp)
// fmt.Println("返回值是", virusResp)
// fmt.Println("返回值是", magicResp)
}
将服务端单独build,监听进程状态
服务端另起进程,监听
package initialize
import (
"os/exec"
"strings"
"time"
"go.uber.org/zap"
"netvine.com/firewall/server/global"
)
func StartWebServer() {
cmd1 := exec.Command("/bin/bash", "./shell/query.sh")
output, _ := cmd1.CombinedOutput()
global.NETVINE_LOG.Info(string(output))
if !strings.Contains(string(output), "./webServer") {
cmd2 := exec.Command("/bin/bash", "./shell/startWebServer.sh")
output, err := cmd2.CombinedOutput()
if err != nil {
global.NETVINE_LOG.Error("启动webServer服务失败", zap.Error(err))
} else {
global.NETVINE_LOG.Info(string(output))
}
}
}
func Monitor() {
go func() {
for {
cmd := exec.Command("/bin/bash", "./shell/query.sh")
output, _ := cmd.CombinedOutput()
if strings.Contains(string(output), "./webServer") {
global.NETVINE_LOG.Info("webServer正常运行:" + string(output))
}
time.Sleep(time.Second * 10)
if !strings.Contains(string(output), "./webServer") {
global.NETVINE_LOG.Info("webServer重启")
go StartWebServer()
global.InitClient() //初始化rpc
}
}
}()
}
query.sh
#! /bin/bash
ps -ef |grep virusServer
startWebServer.sh
#! /bin/bash
cd ../virus && go build -o virusServer
./virusServer
demo:https://github.com/yvonne2345/demo/tree/master/RpcTest
参考链接: