Diakris のマッチメイキングは、マッチングデータをクラスタ内のサーバに分散させ、水平方向のスケーリングを可能にします。
マッチメイキングの定義(ルール)は、HTTP サーバで行います(Diarkis HTTP サーバのメモリ上でデータが管理されるため)。設定の読み込みは、HTTP サーバと TCP/UDP サーバで行う必要があります。
// You MUST import matching package in HTTP server and other servers
import "github.com/Diarkis/diarkis/matching"
func main() {
// You MUST call this to enable matching package (MatchMaker)
matching.Setup("absolute path to a configuration file or an empty string")
// other things to do here
diarkis.Start()
}
マッチメイキングにアイテムを追加する方法
マッチメイキングで検索・マッチングできるようにするためには、"add" が必要です。追加するアイテムは TTL を短く設定し、不要になるまで "add" し続けることをお勧めします。add は比較的低負荷な処理ですが、"remove" の負荷は比較的高いためです。
注: 最大 TTL は60秒です。60秒以上アイテムを利用する場合、必要がなくなるまで繰り返しアイテムを add する必要があります。
NOTE: この処理は HTTP, TCP, UDP/RUDP のどこにでも実装することが可能です。
下の例は、マッチメイキングに Room を追加する方法です
// Match making item property to be searched by
props := make(map[string]int)
props["level"] = 30
props["rank"] = 7
// Unique name of the match-making definition to add the room to
matchingName := "levelAndRank"
// roomMetadata will be retrieved as the search results.
data := make(map[string]interface{})
data["roomID"] = roomID
data["roomType"] = 2
data["roomName"] = "Room of level 30 and rank 7"
// TTL of the room in match-making. TTL is in seconds
ttl := int64(30)
// relayLimit is the number of server nodes to send the data to at a time:
// Greater the value, the faster and more CPU intense it is
relayLimit := 2
matching.Add(matchingName, roomID, props, roomMetadata, ttl, relayLimit)
マッチメイキングからアイテムを削除する方法
注: "remove" の処理負荷は高いので、なるべく TTL や "add" を使うことをお勧めします。
NOTE: この処理は HTTP, TCP, UDP/RUDP のどこにでも実装することが可能です。
// match-making definition name to remove items from
matchingName := "levelAndRank"
// Unique ID list of items to be removed
idlist := []string{ roomIDA, roomIDB }
// relayLimit is the number of server nodes to send the data to at a time:
// Greater the value, the faster and more CPU intense it is
relayLimit := 2
matching.Remove(matchingName, idlist, relayLimit)
マッチメイキングでの検索方法
どのマッチメイキング定義で検索するかを選択する必要があります。複数のマッチメイキング定義名を渡すことで、複数のマッチメイキング定義を検索することができます。検索の順序は、search 関数に渡されたマッチメイキング定義の配列の順序と同じになります。
NOTE: この処理は HTTP, TCP, UDP/RUDP のどこにでも実装することが可能です。
/**
* muse import the following:
*
* github.com/Diarkis/diarkis/matching
* github.com/Diarkis/diarkis/room
* github.com/Diarkis/diarkis/util
*
*/
matchingNames := []string{ "levelAndRank" }
// Search conditions
conds := make(map[string]int)
conds["level"] = 14
conds["rank"] = 3
// How many search results you require
howmany := 10
matching.Search(matchingNames, conds, howmany, func(err error, results []interface{}) {
if err != nil {
// Handle error
return
}
// util.Waterfall executes a list of functions in order
operations := make([]func(error), len(results))
for i := range results {
operations[i] = tryToJion
}
utill.Waterfall(operations, done)
index := 0
// We try the rooms we found
func tryToJoin(next func(error)) {
if index == len(results) {
// We are tried all rooms we found, but none worked
// try matching.Search again
done(nil)
return
}
roomID := results[index]["roomID"].(string)
room.Join(roomID, userData, ver, cmd, func(err error, members []string, owner string, createdTime int64, props map[string]interface{}) {
if err != nil {
// this room was no good, remove from MatchMaker
for _, matchingName := range {
// we assume roomID is used as a unique ID with matching.Addd
matching.Remove(matchingName, roomID)
}
// We have failed to join the room - try the next room
index++
next(nil)
return
}
// We have joined the room successfully - skip the rest of the rooms
done(nil)
})
}
// This function will be called when everything is finished
func done(err error) {
if err != nil {
// Handle error
return
}
logger.Debug("We are done!")
}
})