0

/ dev/ttyS02でシリアルデバイスと対話するWebアプリケーションを作成しました。問題は、私の現在のメッセージングおよびキューイングソリューションです。以下をお読みください。

アプリケーションとpyserial間の通信ブリッジは次のとおりです。

  • 私のWebアプリケーションは、PHPを介してMySQLのd_requestsテーブルにリクエストレコードを挿入します。挿入されたレコードの処理済み列は0に設定されます。挿入されたレコードのIDは$id変数に保存され、PHPアプリケーションはループ状態に入り、$idをルックアップ参照として使用してd_requests[processed]列=1かどうかを継続的にチェックします。 。

  • 処理された列が0であるd_requestsテーブルのレコードを毎秒チェックするPythonデーモンサービスがあります。これは新しいリクエストと見なされます。(ソースコード-pythonサービスを参照してください)

  • 次に、Pythonサービスはレコードの情報を使用して、pyserialを介してポートに接続します。

  • 要求されたアクションが実行されます。次に、レコードの処理済み列が1に更新され、他のいくつかのフィールドも更新されます。これにより、レコードが処理済みとしてマークされます。

  • 次に、PHP制御ブロックはループを終了し(ポイント1)、結果をjsonとしてJSアプリケーションに返します。ここでユーザーに提示されます。

いくつかの注意点

  • シリアルデバイスは、250ミリ秒ごとに1つの要求を処理できます。
  • Pythonデーモンサービスは、d_requestsテーブルを監視して、処理された列が1秒ごとに0であるレコードを探します。
  • 私のWebアプリケーションがPythonデーモンサービスと通信するのは
    、d_requestsテーブルにリクエストレコードを挿入することによるMySQLDBだけです。
  • PHPブロックコードを使用して、挿入されたIDを毎秒使用してリクエストを検索し、処理された列が1に更新されているかどうかを確認します。

私の懸念

単一障害点

デーモンサービスが実行されていない場合、シリアルリクエストは実行できません

極端なリソース使用量

シリアルデバイスへの1秒あたりのリクエスト数は約4〜5と予想されます。メッセージを処理するために現在の実装を使用すると、PHPアプリケーションとPythonデーモン/サービスが接続してDBでクエリを実行し、リクエストの処理に遅延が発生するため、DBは時間外に動作し、CPU使用率が高くなります。

結論:現在のメッセージングおよびキューイングソリューションを改善するためのより良い方法はありますか?この場合、pyserial Webサービスはうまく機能すると思います。たとえば、シリアルポートは次のようになります。Webソケットに接続されています。host:<7000>と、PHPを介してリクエストを送信し、Webサービスからの応答を待つことができます。残念ながら、これを行う方法がわかりません。

何か案は?

ありがとうございました

ソースコード

Pythonサービス

    import sys, time
    from daemon import Daemon
    import MySQLdb 

#Database parameters
config = {"host":"localhost","username":"root","password":"cake","database":"mydb"}

#Check if MySQLdb library is present
try:
    conn = MySQLdb.connect(config['host'],config['username'],config['password'],config['database'])
except MySQLdb.Error, e:
    print "Error %d: %s" % (e.args[o], e.args[1])
    sys.exit(1);

#Check if pyserial library is present
try:
    import serial
except ImportError:
    print "Error,pySerial module not installed"
    sys.exit(1);

#Create DB cursor  
#cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
#Declare global variables here
class MyDaemon(Daemon): 
    def run(self):
        while True:
            time.sleep(2)
            cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)
            data = ''
            try:
                cursor.execute ("""SELECT * FROM d_requests where processed = 0""")
                rows=cursor.fetchall()
                print "Waiting for requests..."
            except MySQLdb.Error as detail:
                print "MySQL Error,",detail
            if len(rows) == 0:
                cursor.close()
                print "No request found..."
                continue
            for row in rows:
                try:                
                    print "Processing request..."                   
                    ser = serial.Serial(port=row['port'],
                    baudrate = row['baud'],
                    bytesize = row['bytesize'], #8
                    parity = row['parity'], #serial.PARITY_NONE or N or C
                    stopbits = row['stopbits'], #1
                    timeout = row['wait_for_reply'], #0.5
                    xonxoff = row['sw_flowcontrol'], #0
                    rtscts = row['hw_flowcontrol']) #0                  
                    #Send command to device
                    ser.write(row['request_string'] + "\r")
                    #Read device response                   
                    data = ser.read(100)#TBD:This value needs to be changeable,not always 100 bytes
                    ser.close()
                    print "RESULT : " + data                    
                except (serial.SerialException, AttributeError, NameError) as detail:
                    data = "Error, could not open port"
                    print data                  
                except serial.SerialTimeoutException as detail:
                    data = "Error, port connection timeout" #Error ,detail
                    print data
                except:
                    data = "Error,Unexpected error"
                    print data              
                finally:
                    #ser.close()
                    try:
                        cursor.execute("""UPDATE d_requests SET processed = %s, result_string = %s WHERE id = %s""",(1,data,row['id']))
                    except MySQLdb.Error as detail:
                        print "MySQL Error,",detail
                #cursor.commit() for innoDB table engines
            cursor.close()
if __name__ == "__main__":
    daemon = MyDaemon('/tmp/daemon-example.pid')
    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            daemon.start()          
        elif 'stop' == sys.argv[1]:
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            daemon.restart()
        elif 'foreground' == sys.argv[1]: #this runs the daemon in the foreground
            daemon.run()
        else:
            print "Unknown command"
            sys.exit(2)
        sys.exit(0)
    else:
        print "usage: %s start|stop|restart" % sys.argv[0]
        sys.exit(2)
4

2 に答える 2

1

現在のメッセージングおよびキューイングソリューションを改善するためのより良い方法はありますか?

あなたは賭けます!それらはメッセージキューと呼ばれ、素晴らしいです。

私のお気に入りは、memcachedをもたらしたのと同じチームによって書かれたGearmanです。PHPPythonのバインディングがあります。実際には、RPCサービスほどのメッセージキューではありません。とにかく、一方の環境からメソッドを呼び出して、もう一方の環境でそれらを処理することができます。

この場合、Pythonでシリアルインターフェースコードを記述し、Gearman関数として実行できるすべてのことを公開する必要があります。デーモンとして開いたままになります。PHPコードは、Gearmanを介してこれらの関数を呼び出すことができます。

于 2011-03-11T00:11:31.233 に答える
0

同様のニーズを調査しています。これまでのところ、「ser2net」デーモンと「termnetd」デーモンが役に立ちました。

于 2011-08-25T17:35:50.043 に答える