avatar of 发明者量化-小小梦 发明者量化-小小梦
پر توجہ دیں نجی پیغام
4
پر توجہ دیں
1271
پیروکار

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: توسیعی API بمقابلہ حکمت عملی بلٹ ان HTTP سروس

میں تخلیق کیا: 2024-12-12 18:33:26, تازہ کاری: 2025-05-16 15:53:52
comments   0
hits   583

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: توسیعی API بمقابلہ حکمت عملی بلٹ ان HTTP سروس

دیباچہ

ٹریڈنگ ویو ویب ہکس سے منسلک ہونے کے بارے میں پلیٹ فارم کی لائبریری میں کئی مضامین موجود تھے، جو بیرونی سسٹمز سے سگنلز کی بنیاد پر تجارت کو چلانے کی اجازت دیتے تھے، اس وقت پلیٹ فارم میں بلٹ ان HTTP سروس فنکشن نہیں تھا جو JavaScript زبان کو سپورٹ کرتا تھا۔ پلیٹ فارم کا توسیعی API انٹرفیس استعمال کیا جاتا ہے:CommandRobotسیدھے الفاظ میں، بیرونی سگنل کی http/https کی درخواست FMZ پلیٹ فارم کو بھیجی جاتی ہے، اور پلیٹ فارم سگنل کو حکمت عملی کے تعامل کے پیغام کے طور پر حکمت عملی پروگرام کو بھیجتا ہے۔

جیسے جیسے پلیٹ فارم تیار اور اعادہ ہوتا ہے، بہت سی نئی خصوصیات کو اپ گریڈ اور اپ ڈیٹ کیا گیا ہے۔ بیرونی سگنلز حاصل کرنے کے لیے نئے حل بھی ہیں۔ ہر حل کے اپنے فوائد ہیں، اس مضمون میں ہم مل کر اس موضوع پر بات کریں گے۔

API انٹرفیس کو بڑھانے کے لیے FMZ پلیٹ فارم استعمال کریں۔

بیرونی نظاموں سے جڑنے کے لیے اس طریقہ کو استعمال کرنے کے فوائد یہ ہیں کہ یہ نسبتاً آسان، انتہائی محفوظ ہے، اور پلیٹ فارم کے توسیعی API انٹرفیس کے استحکام پر انحصار کرتا ہے۔

بیرونی سگنلز حاصل کرنے کا عمل:

بیرونی نظام (ٹریڈنگ ویو ویب ہک) –> FMZ توسیعی API سروس –> حکمت عملی حقیقی مارکیٹ

  1. ایکسٹرنل سسٹم (ٹریڈنگ ویو ویب ہُک): مثال کے طور پر، ٹریڈنگ ویو پر چلنے والا PINE اسکرپٹ ایک الارم سیٹ کر سکتا ہے، جو ٹرگر ہونے پر سیٹ ویب ہُک url ایڈریس پر ایک HTTP درخواست بھیجے گا۔
  2. FMZ توسیعی API سروس: انٹرفیس تک کامیابی سے رسائی کے بعد، پلیٹ فارم معلومات کو آگے بڑھاتا ہے اور اسے ایک انٹرایکٹو پیغام کے طور پر حکمت عملی حقیقی مارکیٹ میں بھیجتا ہے۔
  3. حکمت عملی کا نفاذ: حکمت عملی کے نفاذ میں، آپ انٹرایکٹو پیغامات کو سننے کے لیے GetCommand فنکشن کو ڈیزائن کر سکتے ہیں اور پیغامات کا پتہ لگانے کے بعد مخصوص کارروائیوں کو انجام دے سکتے ہیں۔

سگنلز وصول کرنے کے لیے براہ راست ایک سروس بنانے کے لیے بلٹ ان Http سروس کے استعمال کے مقابلے میں، درمیان میں ایک اضافی قدم ہے (پلیٹ فارم کی منتقلی)۔

حکمت عملی بلٹ ان Http سروس

جب پلیٹ فارم جاوا اسکرپٹ لینگویج کے بلٹ ان Http سروس فنکشن کو سپورٹ کرتا ہے، تو آپ بیرونی سگنلز کو سننے کے لیے براہ راست ایک کنکرنٹ سروس بنا سکتے ہیں۔ فوائد یہ ہیں: بنائی گئی Http سروس ایک الگ تھریڈ ہے اور یہ مرکزی فنکشن منطق کو متاثر نہیں کرتی ہے اور یہ گیٹ کمانڈ فنکشن کی طرح براہ راست بیرونی سگنلز کی نگرانی کر سکتی ہے، یہ ٹرانسفر لنک کو ختم کر دیتی ہے۔

بیرونی سگنلز حاصل کرنے کا عمل:

بیرونی نظام (ٹریڈنگ ویو ویب ہک) –> حکمت عملی لائیو ٹریڈنگ

  1. ایکسٹرنل سسٹم (ٹریڈنگ ویو ویب ہُک): مثال کے طور پر، ٹریڈنگ ویو پر چلنے والی PINE اسکرپٹ ایک الارم سیٹ کر سکتی ہے، جب یہ سیٹ ویب ہُک url ایڈریس کو ایک سگنل کے طور پر بھیجے گا۔
  2. حکمت عملی کا نفاذ: حکمت عملی بیرونی سگنلز کو براہ راست وصول کرنے کے لیے ایک ساتھ Http سروس چلاتی ہے۔

یہ حل ایک قدم بچاتا ہے، لیکن سیکیورٹی کو بہتر بنانے کے لیے، https سروس کو کنفیگر کرنا بہتر ہے، جس کے لیے کچھ محنت درکار ہے۔ توسیع شدہ API کے استعمال سے یہ قدرے زیادہ پریشان کن ہے۔

ٹیسٹ کوڈ

دو حلوں کی جانچ کریں مندرجہ ذیل حکمت عملی بیرونی سگنلز کی نقل کرنے کے لیے ہر چکر میں بیک وقت 10 HTTP/HTTPS درخواستیں بھیجے گی۔ پھر حکمت عملی “انٹریکشن میسیجز” اور “Http سروس تھریڈ کے ذریعے دھکیلے گئے پیغامات” کی نگرانی کرتی ہے۔ پھر حکمت عملی پروگرام بیرونی سگنل کے پیغام کو موصول ہونے والے سگنل کے ساتھ ایک ایک کر کے ملاتا ہے، پتہ لگاتا ہے کہ آیا سگنل کا نقصان ہے، اور وقت کی کھپت کا حساب لگاتا ہے۔

var httpUrl = "http://123.123.123.123:8088/CommandRobot"
var accessKey = ""
var secretKey = ""

function serverFunc(ctx) {
    var path = ctx.path()
    if (path == "/CommandRobot") {
        var body = ctx.body()
        threading.mainThread().postMessage(body)
        ctx.write("OK")
        // 200
    } else {
        ctx.setStatus(404)
    }
}

function createMsgTester(accessKey, secretKey, httpUrl) {
    var tester = {}
    
    tester.currentRobotId = _G()
    tester.arrSendMsgByAPI = []
    tester.arrSendMsgByHttp = []
    tester.arrEchoMsgByAPI = []
    tester.arrEchoMsgByHttp = []
    tester.idByAPI = 0
    tester.idByHttp = 0

    var sendMsgByAPI = function(msgByAPI, robotId, accessKey, secretKey) {
        var headers = {
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36",
            "Content-Type": "application/json"
        }
        HttpQuery(`https://www.fmz.com/api/v1?access_key=${accessKey}&secret_key=${secretKey}&method=CommandRobot&args=[${robotId},+""]`, {"method": "POST", "body": JSON.stringify(msgByAPI), "headers": headers})
    }

    var sendMsgByHttp = function(msgByHttp, httpUrl) {
        HttpQuery(httpUrl, {"method": "POST", "body": JSON.stringify(msgByHttp)})
    }

    tester.run = function() {
        var robotId = tester.currentRobotId

        for (var i = 0; i < 10; i++) {
            var msgByAPI = {"ts": new Date().getTime(), "id": tester.idByAPI, "way": "ByAPI"}            
            tester.arrSendMsgByAPI.push(msgByAPI)
            tester.idByAPI++
            threading.Thread(sendMsgByAPI, msgByAPI, robotId, accessKey, secretKey)

            var msgByHttp = {"ts": new Date().getTime(), "id": tester.idByHttp, "way": "ByHttp"}
            tester.arrSendMsgByHttp.push(msgByHttp)
            tester.idByHttp++
            threading.Thread(sendMsgByHttp, msgByHttp, httpUrl)
        }
    }

    tester.getEcho =function(msg) {
        if (msg["way"] == "ByAPI") {
            tester.arrEchoMsgByAPI.push(msg)
        } else {
            tester.arrEchoMsgByHttp.push(msg)
        }
    }

    tester.deal = function() {
        var tbls = []
        for (var pair of [[tester.arrEchoMsgByHttp, tester.arrSendMsgByHttp, "ByHttp"], [tester.arrEchoMsgByAPI, tester.arrSendMsgByAPI, "ByAPI"]]) {
            var receivedMessages = pair[0]
            var sentMessages = pair[1]
            var testType = pair[2]

            var receivedMap = new Map()
            receivedMessages.forEach(message => {
                receivedMap.set(message["id"], message)
            })
            
            var matchedPairs = []
            var timeDifferences = []
            for (var sentMessage of sentMessages) {
                var receivedMessage = receivedMap.get(sentMessage["id"])
                if (receivedMessage) {
                    matchedPairs.push([JSON.stringify(sentMessage), JSON.stringify(receivedMessage), receivedMessage["ts"] - sentMessage["ts"]])
                    timeDifferences.push(receivedMessage["ts"] - sentMessage["ts"])
                } else {
                    Log("no matched sentMessage:", sentMessage, "#FF0000")
                }
            }
            
            var averageTimeDifference = timeDifferences.reduce((sum, diff) => sum + diff, 0) / timeDifferences.length
            
            var tbl = {
                "type": "table",
                "title": testType + " / averageTimeDifference:" + averageTimeDifference,
                "cols": ["send", "received", "ts diff"],
                "rows": []
            }

            for (var pair of matchedPairs) {
                tbl["rows"].push(pair)
            }

            tbls.push(tbl)
            Log(testType, ", averageTimeDifference:", averageTimeDifference, "ms")
        }

        tester.arrSendMsgByAPI = []
        tester.arrSendMsgByHttp = []
        tester.arrEchoMsgByAPI = []
        tester.arrEchoMsgByHttp = []

        return tbls
    }

    return tester
}

function main() {
    __Serve("http://0.0.0.0:8088", serverFunc)

    var t = createMsgTester(accessKey, secretKey, httpUrl)
    while (true) {
        Log("测试开始...", "#FF0000")
        t.run()

        var beginTS = new Date().getTime()
        while (new Date().getTime() - beginTS < 60 * 1000) {
            var cmd = GetCommand()
            if (cmd) {
                try {
                    var obj = JSON.parse(cmd)
                    obj["ts"] = new Date().getTime()
                    t.getEcho(obj)
                } catch (e) {
                    Log(e)
                }
            }
            
            var msg = threading.mainThread().peekMessage(-1)
            if (msg) {
                try {
                    var obj = JSON.parse(msg)
                    obj["ts"] = new Date().getTime()
                    t.getEcho(obj)                
                } catch (e) {
                    Log(e)
                }
            }
        }
        Log("等待结束...", "#FF0000")
                
        var tbls = t.deal()
        LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
        Sleep(20000)
    }
}

اگر جانچ کر رہے ہیں، تو آپ کو FMZ پلیٹ فارم کی مخصوص سرور IP ایڈریس اور توسیعی API KEY کو پُر کرنے کی ضرورت ہے۔

var httpUrl = "http://123.123.123.123:8088/CommandRobot"
var accessKey = "xxx"
var secretKey = "xxx"
  1. سرور فنکشن بیرونی سگنلز کی نگرانی کے لیے ایک ساتھ Http سروس تخلیق کرتا ہے۔ توسیع شدہ API انٹرفیس کے ذریعے موصول ہونے والے بیرونی پیغامات کے لیے، GetCommand فنکشن کو مانیٹر کرنے کے لیے استعمال کیا جاتا ہے۔
  • ایچ ٹی ٹی پی سروس تھریڈ کے ذریعے بھیجے گئے پیغامات: پر منحصر ہےvar msg = threading.mainThread().peekMessage(-1)مانیٹر

  • توسیعی API انٹرفیس کے ذریعے بھیجے گئے تعامل کے پیغامات: پر منحصر ہےvar cmd = GetCommand()مانیٹر

  1. سگنل بھیجنے اور وصول کرنے کے دونوں عمل غیر مسدود ہوتے ہیں۔Threadیاexchange.Goکنکرنٹ فنکشنز کو اب واضح طور پر سمورتی کاموں کے مکمل ہونے کا انتظار کرنے کی ضرورت نہیں ہے (جیسے فنکشنز میں شامل ہونا، فنکشنز کا انتظار کرنا وغیرہ)، اور بنیادی نظام خود بخود وسائل کی ری سائیکلنگ کو سنبھال لے گا (اس کی حمایت کرنے کے لیے میزبان کے تازہ ترین ورژن کی ضرورت ہے)۔
    // 摘录代码片段,发送信号
    tester.run = function() {
        var robotId = tester.currentRobotId

        for (var i = 0; i < 10; i++) {
            var msgByAPI = {"ts": new Date().getTime(), "id": tester.idByAPI, "way": "ByAPI"}            
            tester.arrSendMsgByAPI.push(msgByAPI)
            tester.idByAPI++
            threading.Thread(sendMsgByAPI, msgByAPI, robotId, accessKey, secretKey)   // 并发调用,非阻塞

            var msgByHttp = {"ts": new Date().getTime(), "id": tester.idByHttp, "way": "ByHttp"}
            tester.arrSendMsgByHttp.push(msgByHttp)
            tester.idByHttp++
            threading.Thread(sendMsgByHttp, msgByHttp, httpUrl)                       // 并发调用,非阻塞
        }
    }

    // 摘录代码片段,接收信号
    var cmd = GetCommand()                              // 监听来自扩展API的消息,非阻塞
    var msg = threading.mainThread().peekMessage(-1)    // 监听来自自建Http服务的消息,使用了参数-1,非阻塞

اگلا، آئیے اس ٹیسٹ کے عمل کو دیکھتے ہیں، جہاں معلومات کو براہ راست کوڈ میں بیان کیا جاتا ہے:

function main() {
    __Serve("http://0.0.0.0:8088", serverFunc)      // 在当前策略实例中,创建一个并发的http服务

    var t = createMsgTester(accessKey, secretKey, httpUrl)   // 创建一个用于测试管理的对象
    while (true) {                                           // 策略主循环开始
        Log("测试开始...", "#FF0000")
        t.run()                                              // 每次循环开始,调用测试管理对象的run函数,使用两种方式(1、通过扩展API发送信号,2、直接向当前策略创建的Http服务发送信号),每种方式并发发送10个请求

        var beginTS = new Date().getTime()
        while (new Date().getTime() - beginTS < 60 * 1000) {   // 循环检测来自扩展API的交互消息,循环检测来自自建Http服务的消息
            var cmd = GetCommand()
            if (cmd) {
                try {
                    var obj = JSON.parse(cmd)
                    obj["ts"] = new Date().getTime()        // 检测到交互消息,记录消息,更新时间为收到时间
                    t.getEcho(obj)                          // 记录到对应数组
                } catch (e) {
                    Log(e)
                }
            }
            
            var msg = threading.mainThread().peekMessage(-1)
            if (msg) {
                try {
                    var obj = JSON.parse(msg)
                    obj["ts"] = new Date().getTime()        // 检测到自建的Http服务收到的消息,更新时间为收到时间
                    t.getEcho(obj)                          // ...
                } catch (e) {
                    Log(e)
                }
            }
        }
        Log("等待结束...", "#FF0000")
                
        var tbls = t.deal()                                  // 根据记录的消息,配对,检查是否有未配对的消息,如果有说明有信号丢失
        LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
        Sleep(20000)
    }
}

ٹیسٹ کے نتائج

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: توسیعی API بمقابلہ حکمت عملی بلٹ ان HTTP سروس

FMZ پلیٹ فارم کے بیرونی سگنل کے استقبال پر بحث: توسیعی API بمقابلہ حکمت عملی بلٹ ان HTTP سروس

جانچ کی مدت کے بعد، یہ دیکھا جا سکتا ہے کہ ایچ ٹی ٹی پی طریقہ API کے طریقہ کار کے مقابلے میں اوسطاً تھوڑا کم وقت لیتا ہے۔

حکمت عملی میں سگنلز حاصل کرنے کے لیے ایک بلٹ ان Http سروس موجود ہے، یہ جانچ کا طریقہ بہت سخت نہیں ہے اور درخواست باہر سے آنی چاہیے۔ سادگی کی خاطر اس عنصر کو نظر انداز کیا جا سکتا ہے۔ سگنل کے حصول کے دونوں طریقوں کے لیے، حکمت عملی کی بلٹ ان Http سروس آخر کار ایک لنک کو کم کرتی ہے، اور اس میں تیز رفتار ردعمل ہونا چاہیے۔ سگنل کے استحکام کے لیے، یہ زیادہ اہم ہے کہ سگنل ضائع یا چھوٹ نہ جائے۔ ٹیسٹ کے نتائج سے پتہ چلتا ہے کہ FMZ پلیٹ فارم کا توسیع شدہ API بھی مستحکم ہے، لیکن اس بات کو مسترد نہیں کیا جاتا ہے کہ مختلف عوامل جیسے کہ Http سروس استعمال کرنے سے سگنل کے مسائل پیدا ہو سکتے ہیں۔ براہ راست بیرونی سگنل وصول کرنا بھی ایک بہتر طریقہ ہے۔

یہ مضمون صرف ایک نقطہ آغاز ہے جو کوڈ میں موجود Http سروس کی تصدیق نہیں کی گئی ہے اور یہ صرف میسج ڈیٹا حاصل کرتی ہے، ہم بیرونی ٹریڈنگ ویو سگنلز حاصل کرنے کے لیے ایک بلٹ ان Http سروس ٹیمپلیٹ کو مکمل طور پر نافذ کریں گے۔ پڑھنے کے لیے شکریہ۔