Rpc通信

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

参考链接:

Golang JSONRPC 2.0 范例:使用 gorilla/rpc/v2 实现 - 简单教程,简单编程

Go 每日一库之 rpc - 大俊的博客

RPC入门 - Go语言高级编程

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值