在使用标准功能的 Go 中net/rpc
,我想确定入站 RPC 请求来自哪个 IP 地址。底层http
功能似乎在http.Request
对象中提供了这一点,但我看不到任何从默认 RPC 处理程序(使用设置rpc.HandleHTTP
)中获取的方法。
是否有一些隐藏的机制来获取底层http.Request
,或者我必须做一些更有趣的事情来设置不同的 HTTP 响应器?
据我所知,不可能从默认服务器的某个地方获取地址。
调用请求接收函数的服务调用方法不提供对存储在编解码器中的远程数据的任何访问。
如果 http 处理程序可以注册两次(他们不能),您可能已经覆盖DefaultRPCPath
了 HTTP 处理程序设置的HandleHTTP
. 但这在今天根本不可能。
你可以做的,不用大惊小怪,就是在默认服务器的基础上,用你自己的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
使用您无法访问的私有调试处理程序( )。rpc.debugHTTP
该net/rpc
包的抽象级别比 tcp 或 http 更高。由于它可以使用多个编解码器,因此提供一种获取入站 rpc 的 IP 地址的方法是没有意义的。从理论上讲,有人可以实现一个在 unix 套接字上进行通信的代码,或者使用无线电发射器。
如果您想访问传输层的细节,您将不得不在堆栈中删除一个级别并使用net
ornet/http
目录来创建您的 rpc 服务。
您也可以使用https://github.com/valyala/gorpc而不是 net/rpc,它将客户端地址传递给 RPC 服务器处理程序 -有关详细信息,请参阅http://godoc.org/github.com/valyala/gorpc#HandlerFunc .
似乎目前没有办法在 rpc 函数中执行此操作。有关更多信息,请参阅此链接
这是一个总结。
问:
现在RemoteAddr() 方法只能在客户端拨号到服务器时在net.Conn 上调用来获取RPC 客户端的地址,但是假设您的服务器连接了多个客户端并且每个客户端都在调用一个RPC 导出方法。有没有办法实现从 RPC 方法内部获取调用者远程地址的方法?
func (t *Type) Method(args *Args, reply *string) error {
//类似于
*reply = Caller.RemoteAddr().String()
// 现在谁调用了这个方法?
返回零
}
A:
我很怀疑。这需要 API 更改(不一定是向后不兼容的,但仍然需要重新设计)来提供此功能。