【问题标题】:Determining requester's IP address in RPC call在 RPC 调用中确定请求者的 IP 地址
【发布时间】:2012-09-27 21:14:42
【问题描述】:

在使用标准 net/rpc 功能的 Go 中,我想确定入站 RPC 请求来自哪个 IP 地址。底层的http 功能似乎在http.Request 对象中提供了此功能,但我看不到任何从默认RPC 处理程序(使用rpc.HandleHTTP 设置)中获取此功能的方法。

是否有一些隐藏的机制可以获取底层 http.Request,或者我是否必须做一些更有趣的事情来设置不同的 HTTP 响应器?

【问题讨论】:

  • 为什么要ip地址?
  • @JeremyWall 我需要它来进行日志记录/调试,如果也能对某些东西进行简单的完整性检查,那就太好了。

标签: go rpc


【解决方案1】:

据我所知,无法从默认服务器的某处获取地址。

调用请求接收函数的service call method不提供对存储在编解码器中的远程数据的任何访问。

如果可以注册两次 http 处理程序 (which they can't),则您可以覆盖 DefaultRPCPath 用于由HandleHTTP 设置的 HTTP 处理程序。但这只是not possible today

你可以做的,不用大惊小怪,就是在默认服务器的基础上用你自己的ServeHTTP方法构建一个RPC服务器:

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

type myRPCServer struct {
   *rpc.Server
}

func (r *myRPCServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
   log.Println(req.RemoteAddr)
   r.Server.ServeHTTP(w, req)
}

func (r *myRPCServer) HandleHTTP(rpcPath, debugPath string) {
    http.Handle(rpcPath, r)
}

func main() {
    srv := &myRPCServer{rpc.NewServer()}
    srv.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)

    // ...http listen code...
}

当然,这样做的缺点是您不能再使用rpc.Register。你必须写srv.Register

编辑:我忘了你还需要写自己的HandleHTTP。这样做的原因是,如果您嵌入 RPC 服务器并编写 srv.HandleHTTP,它会在嵌入实例上调用,将嵌入实例传递给 http.Handle(),而忽略您自己对 ServeHTTP 的定义。这有一个缺点,您将无法使用调试路径调试 RPC 服务器,因为服务器的 HandleHTTP 使用您无法访问的 private debug handler (rpc.debugHTTP)。

【讨论】:

  • 这看起来是一个不错的方法,而且我认为这是必要的。不过,我完全是 Go 新手,所以我可能需要一段时间才能将这些部分组合在一起。
【解决方案2】:

您也可以使用https://github.com/valyala/gorpc 代替 net/rpc,它将客户端地址传递给 RPC 服务器处理程序 - 有关详细信息,请参阅 http://godoc.org/github.com/valyala/gorpc#HandlerFunc

【讨论】:

  • 谢谢!大约三年前我从事的项目对我来说早已不复存在,但希望这对将来有同样问题的人有用。
【解决方案3】:

net/rpc 包的抽象级别比 tcp 或 http 更高。由于它可以使用多个编解码器,因此提供一种获取入站 rpc 的 IP 地址的方法是没有意义的。从理论上讲,有人可以实现一个在 unix 套接字上进行通信的代码,或者使用无线电发射器。

如果您想访问传输层的细节,您必须在堆栈中删除一个级别并使用netnet/http 目录来创建您的 rpc 服务。

【讨论】:

  • 我认为它处于更高的抽象级别,但没有理由不能有一个接口来获取底层传输机制。现在的 API 似乎没有为此提供任何未来的钩子,尽管处理程序的存根类型名的接口可能会在未来成为那个。
【解决方案4】:

目前似乎没有办法在 rpc 函数中执行此操作。 请参阅此link 了解更多信息

这是一个摘要。

问:

现在只能调用 RemoteAddr() 方法来获取 RPC 客户端的地址 net.Conn 当客户端拨号到服务器时,但假设您的服务器有多个 连接的客户端,并且每个客户端都在调用 RPC 导出方法。有没有 一种实现从 RPC 内部获取调用者远程地址的方法的方法 方法?

func (t *Type) Method(args *Args, reply *string) 错误{
//类似
*reply = Caller.RemoteAddr().String()
// 现在是谁调用了这个方法?
返回零
}

答:

我很怀疑。这将需要 API 更改(不一定是向后不兼容的 但仍然需要重新设计)来提供这个。

【讨论】:

    猜你喜欢
    • 2017-07-10
    • 1970-01-01
    • 2011-07-31
    • 2015-06-21
    • 2020-03-31
    • 1970-01-01
    • 2020-05-19
    • 2012-04-23
    • 1970-01-01
    相关资源
    最近更新 更多