組成:
- 路由: 分發rpc的服務器 可以現在go語言版的,https://github.com/jcelliott/turnpike
- server: 函數提供者
- client:函數調用方
server和client 可以選擇 https://wamp-proto.org/implementations/index.html
python 例子 http://autobahn.readthedocs.io/en/latest/wamp/examples.html
python爲例 server端
import datetime
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.wamp import ApplicationSession,ApplicationRunner
# from autobahn_autoreconnect import ApplicationRunner
class Component(ApplicationSession):
"""
A simple time service application component.
"""
@inlineCallbacks
def onJoin(self, details):
print("session attached")
def utcnow():
now = datetime.datetime.utcnow()
return now.strftime("%Y-%m-%dT%H:%M:%SZ")
try:
yield self.register(utcnow, u'com.timeservice.now')
except Exception as e:
print("failed to register procedure: {}".format(e))
else:
print("procedure registered")
if __name__ == '__main__':
runner = ApplicationRunner(u"ws://xxx.xxx.com:31000/ws", u"pwd")
runner.run(Component, auto_reconnect=True)
客戶端
from twisted.internet import reactor
from twisted.internet.defer import inlineCallbacks
from autobahn.twisted.wamp import ApplicationSession, ApplicationRunner
class Component(ApplicationSession):
"""
An application component using the time service.
"""
@inlineCallbacks
def onJoin(self, details):
print("session attached")
try:
now = yield self.call(u'com.timeservice.now')
except Exception as e:
print("Error: {}".format(e))
else:
print("Current time from time service: {}".format(now))
self.leave()
def onDisconnect(self):
print("disconnected")
reactor.stop()
if __name__ == '__main__':
runner = ApplicationRunner(u"ws://xxx.xxx.com:31000/ws", u"pwd")
runner.run(Component, auto_reconnect=True)
經過一段時間的測試發現turnpike路由存在一個問題:
當server意外斷網後(拔網線這種), turnpike不會發現這個server已掉線, 重啓server註冊時提示函數已經存在, 必須重啓turnpike
現改用https://github.com/gammazero/nexus
後測試發現nexus也有這個問題,測試方法,但拔掉客戶端的網線再插上,報提示"REGISTER for already registered procedure"
目前通過修改nexus的代碼解決,使得收到註冊消息時永遠是替換方式
dealer.go:register函數
var created string
var regID wamp.ID
// If no existing registration found for the procedure, then create a new
// registration.
if reg == nil { //改成 if true {
regID = d.idGen.Next()
created = wamp.NowISO8601()
reg = ®istration{
dealer.go delCalleeReg函數
if len(reg.callees) == 0 {
delete(d.registrations, regID)
switch reg.match {
default:
if d.procRegMap[reg.procedure] != nil && d.procRegMap[reg.procedure].id == regID {
delete(d.procRegMap, reg.procedure)
}
2018.12.10
使用未按上面修改過的最新的nexus,加上autobahn js或python版可以實現rpc callee的負載均衡
session.register('com.myapp.add2', add2, {
'invoke': "random" //負載方式 "single", "roundrobin", "random", "first", "last"
});
python
yield self.register(utcnow, u'com.timeservice.now1', RegisterOptions(invoke=u'random'))
當時使用最新的autobahn python版客戶端會提示註冊失敗。
性能測試
單核本機caller +本機callee 每秒大約可以到2500個rpc請求 cpu跑滿
異常問題
啓動兩個callee,然後caller循環調用rpc,這時kill掉其中一個callee,有機率caller的call函數不再返回卡死,估計是nexus的bug
用crossbar.io做router就不存在這個問題,而且crossbar.io貌似支持集羣,可以規避router的單點故障,但crossbar.io的單核性能不如nexus