【发布时间】:2013-01-06 07:00:42
【问题描述】:
函数如下:
func Message(worker_ID int, message string, args *Args , reply *int) chan bool {
}
这个函数驻留在主机上,客户端在向主机发送消息时调用它,主机位于不同的地方,所以发送消息需要IP和端口对吗? net.dial() 或 gob 或 rpc 哪种机制有帮助?
【问题讨论】:
函数如下:
func Message(worker_ID int, message string, args *Args , reply *int) chan bool {
}
这个函数驻留在主机上,客户端在向主机发送消息时调用它,主机位于不同的地方,所以发送消息需要IP和端口对吗? net.dial() 或 gob 或 rpc 哪种机制有帮助?
【问题讨论】:
如果您想要一些简单的东西,请查看net/rpc,它将 gob 和网络封装到一个远程过程调用框架中,它应该可以满足您的需求。
服务器
根据文档,运行 HTTP 的服务器
type Args struct {
A, B int
}
type Arith int
func (t *Arith) Multiply(args *Args, reply *int) error {
*reply = args.A * args.B
return nil
}
arith := new(Arith)
rpc.Register(arith)
rpc.HandleHTTP()
l, e := net.Listen("tcp", ":1234")
if e != nil {
log.Fatal("listen error:", e)
}
go http.Serve(l, nil)
客户
此时,客户端可以看到使用方法“Arith.Multiply”的服务“Arith”。要调用一个,拨打服务器然后拨打电话。您还可以进行异步调用,结果在通道中返回。
client, err := rpc.DialHTTP("tcp", serverAddress + ":1234")
if err != nil {
log.Fatal("dialing:", err)
}
args := &server.Args{7,8}
var reply int
err = client.Call("Arith.Multiply", args, &reply)
if err != nil {
log.Fatal("arith error:", err)
}
fmt.Printf("Arith: %d*%d=%d", args.A, args.B, reply)
框架的一个奇怪之处在于,每个远程调用只能有一个输入参数和一个输出参数,这意味着您需要将所有参数包装在 struct 中。
【讨论】:
ifconfig (linux) 或ipconfig (windows) 找到每台服务器的IP 地址。然后,您将找到的 IP 地址填入上面的serverAddress。
//server.go 将提供与主机通信和处理的接口
//workerDead(message string),发送消息等待ack,如果没有ack就代表worker死了
package
main
import(
"fmt"
"io"
"net"
"net/http"
"net/rpc"
"path"
"os"
)
type Flag int
type Args struct{
message string
}
func main() {
flag := new(Flag)
rpc.Register(flag)
rpc.HandleHTTP()
err := http.ListenAndServe(":1234", nil) //ListenAndServe starts an HTTP server with a given address and handler.
//The handler is usually nil, which means to use DefaultServeMux.
if err != nil {
fmt.Println(err.Error())
}
}
//Worker counts the number of hosts
func workerCount() int
{
return db.runCommand( { count: 'id' } ) //mongodb command to count the id
}
// Returns an array of the distinct values of field id from all documents in the workers collection
//In mongodb document is analogous to rdbms table and collection is record
func Worker(worker int) []string{
return db.runCommand ({ distinct: 'workers', key: 'id' } ) //mongodb command to get the array of list of
//workers for column id
}
func Message(worker int, message string, args *Args , reply *int) chan bool {
server, err :=rpc.Dial("tcp","192.168.23.12") //Serve Dials here to send message to host, IP address here is of host
if(err!=nil){
log.Fatal("Dialing", err)
}
var reply bool
args:=Args{message};
err = server.Call(args,&reply);
if(err!=nil){
log.Fatal("Dialing", err)
replaceWorker(); // No reply from worker then call to replace worker
}
fmt.Println("Reply from host", reply);
}
return nil
}
//Replace dead worker of particular project with fresh worker
func replaceWorker(worker_id int,project_id int)
{
db.workers.update( //this query updates workers collection with id=worker_id(id of dead worker)
{ _id: worker_id, _project_id: project_id },
{
//$set: { ' ': 'Warner' },
}
)
}
【讨论】: