拜占庭简单实现

PBFT(拜占庭容错)

基于拜占庭将军问题,一致性的确保主要分为这三个阶段:预准备(pre-prepare)、准备(prepare)和确认(commit)。

其中C为发送请求端,0123为服务端,3为宕机的服务端,具体步骤如下:

  1. Request:请求端C发送请求到任意一节点,这里是0
  2. Pre-Prepare:服务端0收到C的请求后进行广播,扩散至123
  3. Prepare:123,收到后记录并再次广播,1->023,2->013,3因为宕机无法广播
  4. Commit:0123节点在Prepare阶段,若收到超过一定数量的相同请求,则进入Commit阶段,广播Commit请求 5.Reply:0123节点在Commit阶段,若收到超过一定数量的相同请求,则对C进行反馈

代码实现

package main

import (
	"os"
	"fmt"
	"net/http"
	"io"
)

//声明节点信息,代表各个小国家
type nodeInfo struct {
	//标示
	id string
	//准备访问的方法
	path string
	//服务器做出的相应
	writer http.ResponseWriter

}

/存放四个国家的地址
var nodeTable = make(map[string]string)

//拜占庭在Fabric中的使用
func main() {

	//获取执行的参数
	userId :=os.Args[1]//获取执行的第一个参数
	fmt.Println(userId)

	//./main Apple

	//创建四个国家的地址
	nodeTable = map[string]string {
		"Apple":"localhost:1111",
		"MS":"localhost:1112",
		"Google":"localhost:1113",
		"IBM":"localhost:1114",
	}

	node:=nodeInfo{userId,nodeTable[userId],nil}
	fmt.Println(node)

//http协议的回调函数
	//http://localhost:1111/req?warTime=8888
	http.HandleFunc("/req",node.request)
	http.HandleFunc("/prePrepare",node.prePrepare)
	http.HandleFunc("/prepare",node.prepare)
	http.HandleFunc("/commit",node.commit)

	//启动服务器
	if err:=http.ListenAndServe(node.path,nil);err!=nil {
		fmt.Print(err)
	}



}

//此函数是http访问时候req命令的请求回调函数
func (node *nodeInfo)request(writer http.ResponseWriter,request *http.Request){
	//设置允许解析参数
	request.ParseForm()
	//如果有参数值,则继续处理
	if (len(request.Form["warTime"])>0){
		node.writer = writer
		//激活主节点后,广播给其他节点,通过Apple向其他节点做广播
		node.broadcast(request.Form["warTime"][0],"/prePrepare")

	}


}

//由主节点向其他节点做广播
func (node *nodeInfo)broadcast(msg string ,path string ){
	//遍历所有的国家
	for nodeId,url:=range nodeTable {

		if nodeId == node.id {
			continue
		}
		//调用Get请求
		//http.Get("http://localhost:1112/prePrepare?warTime=8888&nodeId=Apple")
		http.Get("http://"+url+path+"?warTime="+msg+"&nodeId="+node.id)
	}

}

func (node *nodeInfo)prePrepare(writer http.ResponseWriter,request *http.Request) {
	request.ParseForm()
	//fmt.Println("hello world")
	//在做分发
	if(len(request.Form["warTime"])>0){
		//分发给其他三个人
		node.broadcast(request.Form["warTime"][0],"/prepare")
	}

}

func (node *nodeInfo)prepare(writer http.ResponseWriter,request *http.Request){

	request.ParseForm()
	//调用验证
	if len(request.Form["warTime"])>0{
		fmt.Println(request.Form["warTime"][0])
	}
	if len(request.Form["nodeId"])>0 {
		fmt.Println(request.Form["nodeId"][0])
	}

	node.authentication(request)
}

var authenticationsuccess = true
var authenticationMap = make(map[string]string)
//获得除了本节点外的其他节点数据
func (node *nodeInfo)authentication(request *http.Request) {

	//接收参数
	request.ParseForm()

	if authenticationsuccess!=false  {
		if len(request.Form["nodeId"])>0 {
			authenticationMap[request.Form["nodeId"][0]]="ok"
		}
	}

	if len(authenticationMap)>len(nodeTable)/3 {
		//则拜占庭原理实现,通过commit反馈给浏览器
		node.broadcast(request.Form["warTime"][0],"/commit")

	}
}

func (node *nodeInfo)commit(writer http.ResponseWriter,request *http.Request){

	//给浏览器反馈相应
	io.WriteString(node.writer,"ok")

}
拜占庭简单实现

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章