向一组主机发送带有确认的消息

Posted

技术标签:

【中文标题】向一组主机发送带有确认的消息【英文标题】:Sending a message to set of hosts with acknowledgements 【发布时间】:2013-01-06 07:00:42 【问题描述】:

函数如下:

func Message(worker_ID int, message string, args *Args , reply *int) chan bool 

这个函数驻留在主机上,客户端在向主机发送消息时调用它,主机位于不同的地方,所以发送消息需要IP和端口对吗? net.dial()gobrpc 哪种机制有帮助?

【问题讨论】:

【参考方案1】:

如果您想要一些简单的东西,请查看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.Args7,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 中。

【讨论】:

是的,谢谢哥们,我在 Go 网络文档中看到了这个。但我不明白,因为我有一组位于不同位置的主机,我如何使用它向他们发送消息,因为这里没有远程主机的 IP 规范...... 最简单的方法是记下程序中的远程主机 IP。您可以通过登录并使用ifconfig (linux) 或ipconfig (windows) 找到每台服务器的IP 地址。然后,您将找到的 IP 地址填入上面的serverAddress 是的,我同时拥有服务器和主机的 IP,但假设主机的 IP 为 192.168.12.4,那么服务器如何向主机发送消息?服务器应该将这个 ip 放在哪里以在上面的代码中发送消息? 你有两个选择。您可以让客户端轮询服务器上的消息,或者您也可以在客户端上运行服务器代码,以便服务器可以向客户端发送消息。 @KarimkhanPathan,当你有一个 TCP 连接(连接到服务器的客户端)时,你已经有一个双向通信通道,所以连接的客户端根据定义知道将它的 ACK 发送到它的现有的连接。所以我只是让客户端保持连接并通过 TCP 实现有线协议(例如使用 gob)。【参考方案2】:

//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:=Argsmessage;
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' ,
   

)


【讨论】:

缩进代码确实有助于提高可读性,尤其是像 go 这样的语言

以上是关于向一组主机发送带有确认的消息的主要内容,如果未能解决你的问题,请参考以下文章

初始TCP协议

ActiveMQ的学习(ActiveMQ的消息事务和消息的确认机制)

Web Socket - Spring:确认收到的消息

RabbitMQ消息确认机制—消息发送确认和 消息接收确认

RabbitMQ的消息确认机制

RabbitMQ的消息确认机制