وسائل لوڈ ہو رہے ہیں... لوڈنگ...

ایف ایم زیڈ پلیٹ فارم کی بیرونی سگنل وصولی پر تبادلہ خیال: توسیع شدہ اے پی آئی بمقابلہ حکمت عملی بلٹ ان HTTP سروس

مصنف:FMZ~Lydia, تخلیق: 2024-12-13 13:12:31, تازہ کاری: 2024-12-16 11:32:35

img

پیش لفظ

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

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

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

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

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

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

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

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

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

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

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

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

  1. بیرونی نظام (ٹریڈنگ ویو ویب ہک): مثال کے طور پر ، ٹریڈنگ ویو پر چلنے والی پائن اسکرپٹ الارم ترتیب دے سکتی ہے ، جو ٹرگر ہونے پر سگنل کے طور پر مقرر کردہ ویب ہک یو آر ایل ایڈریس پر HTTP درخواست بھیجے گی۔
  2. حکمت عملی لائیو ٹریڈنگ: حکمت عملی براہ راست بیرونی سگنل وصول کرنے کے لئے بیک وقت ایک HTTP سروس چلاتی ہے۔

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

ٹیسٹ کوڈ

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

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("Test start...", "#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("Waiting is over...", "#FF0000")
                
        var tbls = t.deal()
        LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
        Sleep(20000)
    }
}

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

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

  • توسیع شدہ API انٹرفیس کی طرف سے آگے بھیجنے والے تعامل کے پیغامات: کی طرف سے نگرانیvar cmd = GetCommand().

  1. سگنل بھیجنے اور وصول کرنے کے عمل غیر مسدود ہیں۔ پلیٹ فارم بنیادی ملٹی تھریڈڈ ریسورس ریکوری میکانزم کو بہتر بناتا ہے۔ متوازی افعال جیسےThreadیاexchange.Go، متوازی کاموں کے مکمل ہونے کا واضح طور پر انتظار کرنے کی ضرورت نہیں ہے (جیسے فنکشنز کو جوڑنا ، فنکشنز کو انتظار کرنا ، وغیرہ) ۔ بنیادی نظام خود بخود وسائل کی بازیابی کو سنبھالے گا (اس کی حمایت کے لئے ڈوکر کے تازہ ترین ورژن کی ضرورت ہے) ۔
    // Extract code snippet, send signal
    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)   // Concurrent calls, non-blocking

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

    // Extract code snippet, receiving signal
    var cmd = GetCommand()                              // Listen for messages from the extension API, non-blocking
    var msg = threading.mainThread().peekMessage(-1)    // Listen for messages from self-built Http service, using parameter -1, non-blocking

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

function main() {
    __Serve("http://0.0.0.0:8088", serverFunc)      // Create a concurrent http service in the current strategy instance

    var t = createMsgTester(accessKey, secretKey, httpUrl)   // Create an object for test management
    while (true) {                                           // The strategy main loop starts
        Log("Test start...", "#FF0000")
        t.run()                                              // At the beginning of each loop, the run function of the test management object is called in two ways (1. Sending signals through the extended API, 2. Sending signals directly to the Http service created by the current strategy), each way sends 10 requests concurrently

        var beginTS = new Date().getTime()
        while (new Date().getTime() - beginTS < 60 * 1000) {   // Loop detection of interactive messages from extended APIs and messages from self-built Http services
            var cmd = GetCommand()
            if (cmd) {
                try {
                    var obj = JSON.parse(cmd)
                    obj["ts"] = new Date().getTime()        // Detect interactive messages, record messages, and update time to the time received
                    t.getEcho(obj)                          // Record to the corresponding array
                } catch (e) {
                    Log(e)
                }
            }
            
            var msg = threading.mainThread().peekMessage(-1)
            if (msg) {
                try {
                    var obj = JSON.parse(msg)
                    obj["ts"] = new Date().getTime()        // Detects the message received by the self-built Http service, and the update time is the receiving time
                    t.getEcho(obj)                          // ...
                } catch (e) {
                    Log(e)
                }
            }
        }
        Log("Waiting is over...", "#FF0000")
                
        var tbls = t.deal()                                  // Pair according to the recorded messages and check if there is any unpaired message. If there is, it means the signal is lost.
        LogStatus(_D(), "\n`" + JSON.stringify(tbls) + "`")
        Sleep(20000)
    }
}

ٹیسٹ کے نتائج

img

img

ٹیسٹنگ کی ایک مدت کے بعد، یہ مشاہدہ کیا جا سکتا ہے کہ HTTP طریقہ API طریقہ کے مقابلے میں اوسطا تھوڑا کم وقت لگتا ہے.

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

یہ مضمون صرف ایک نقطہ آغاز ہے، اس پر بحث کرنے کا خیر مقدم، پڑھنے کے لئے شکریہ.


مزید