在 RPC 调用中确定请求者的 IP 地址

Posted

技术标签:

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

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

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

【问题讨论】:

为什么要ip地址? @JeremyWall 我需要它来进行日志记录/调试,如果也能对某些东西进行简单的完整性检查,那就太好了。 【参考方案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 := &myRPCServerrpc.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 更改(不一定是向后不兼容的 但仍然需要重新设计)来提供这个。

【讨论】:

以上是关于在 RPC 调用中确定请求者的 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章

RabbitMQ 远程过程调用(RPC)

既然有http 请求,为啥还要用rpc调用

如何尝试捕获对离线 RPC 服务器的 RPC 调用?

RPC原理解析

我不懂微服务:RPC远程调用

我不懂微服务:RPC远程调用