python實現dubbo接口的調用


由於公司使用基於Java語言的
Dubbo技術棧,而本人對Python技術棧更為熟悉。為了使不懂JAVA代碼的同學也能進行Dubbo接口層的測試,總結一個通過python實現dubbo接口調用的實現方案。

一、實現原理:

根據Dubbo官方文檔中提到的:dubbo可以通過telnet命令進行服務治理,可以通過telnet鏈接dubbo服務,再通過invoke方法調用dubbo接口
詳情見​​http://dubbo.apache.org/zh-cn/docs/user/references/telnet.html
在這里插入圖片描述在這里插入圖片描述

而在Python中有一個第三方包 telnetlib,所以我們可以通過這個包來執行telnet命令,進而對dubbo接口進行調用

通過上面官方文檔截圖,我們可以看到,當我們拿到dubbo服務的IP和端口號,就能去調用指定的dubbo接口了。下面,讓我們一步步來實現

二、dubbo架構:

在這里插入圖片描述

調用關系說明 服務容器負責啟動,加載,運行服務提供者。 服務提供者在啟動時,向注冊中心注冊自己提供的服務。
服務消費者在啟動時,向注冊中心訂閱自己所需的服務。
注冊中心返回服務提供者地址列表給消費者,如果有變更,注冊中心將基於長連接推送變更數據給消費者。
服務消費者,從提供者地址列表中,基於軟負載均衡算法,選一台提供者進行調用,如果調用失敗,再選另一台調用。
服務消費者和提供者,在內存中累計調用次數和調用時間,定時每分鍾發送一次統計數據到監控中心。 Dubbo
架構具有以下幾個特點,分別是連通性、健壯性、伸縮性、以及向未來架構的升級性。

通過上面架構圖我們可以類似 zookeeper 這樣的服務注冊中心找到對應的服務,所部署的機器和端口
在這里插入圖片描述
也通過dubbo-monitor上面進行查詢在這里插入圖片描述

三、python實現dubbo的調用

通過上述收到查到到要調用的dubbo接口所處的服務器IP和端口,我們就可以通過python實現dubbo的調用了。詳細代碼如下:

import re
import telnetlib
import time
import logging

logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

'''
方法調用案例:
conn = InvokeDubboApi('127.0.0.1:88888')
data = {
    'dubbo_service': 'xxx.xxx.xx.xxxx.xxxx.xxxx.Service',
    'dubbo_method': 'xxxxx',
    'parameters': ({"age":41,"name":"tom"},"sh",564645,)
    }
invoke = json.loads(conn.invoke_dubbo_api(data))
conn.logout()
'''

class TelnetClient(object):
    """通過telnet連接dubbo服務, 執行shell命令, 可用來調用dubbo接口
    """

    def __init__(self, server_host, server_port):
        self.conn = telnetlib.Telnet()
        self.server_host = server_host
        self.server_port = server_port

    # telnet登錄主機
    def connect_dubbo(self):
        try:
            logging.info("telent連接dubbo服務端: telnet {} {} ……".format(self.server_host, self.server_port))
            self.conn.open(self.server_host, port=self.server_port)
            return True
        except Exception as e:
            logging.info('連接失敗, 原因是: {}'.format(str(e)))
            return False

    # 執行傳過來的命令,並輸出其執行結果
    def execute_command(self, command):
        # 執行命令
        cmd = 'invoke {}\n'.format(command).encode("utf-8")
        self.conn.write(cmd)
        # 初始化調用次數
        invoke_count = 0
        # 若調用無返回時,記錄次數並重試
        result = self.conn.read_very_eager().decode(encoding='utf-8').split('\r\n')[0]
        while result == '':
            time.sleep(1)
            result = self.conn.read_very_eager().decode(encoding='utf-8').split('\r\n')[0]
            invoke_count += 1
            if invoke_count>=5:
                logging.info("調用dubbo接口超過五次,調用失敗")
                return '調用dubbo接口失敗'
        return result
    # 退出telnet
    def logout_host(self):
        self.conn.write(b"exit\n")
        logging.info("登出成功")

class InvokeDubboApi(object):

    def __init__(self, content):
        #解析dubbo部署的ip和port
        try:
            dubboaddrre = re.compile(r"([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+)", re.I)
            result = dubboaddrre.search(str(content)).group()
            server_host = result.split(":")[0]
            server_port = result.split(":")[1]
            logging.info("獲取到dubbo部署信息" + result)
        except Exception as e:
            raise Exception("獲取dubbo部署信息失敗:{}".format(e))

        try:
            self.telnet_client = TelnetClient(server_host, server_port)
            self.login_flag = self.telnet_client.connect_dubbo()
        except Exception as e:
            logging.info("invokedubboapi init error" + e)

    #調用dubbo接口
    def invoke_dubbo_api(self, data):
        cmd = data.get("dubbo_service") + "." + data.get("dubbo_method") + "{}".format(data.get("parameters"))
        logging.info("調用命令是:{}".format(cmd))
        resp = None
        try:
            if self.login_flag:
                result= self.telnet_client.execute_command(cmd)
                logging.info("接口響應是,result={}".format(resp))
                return result
            else:
                logging.info("登陸失敗!")
        except Exception as e:
            raise Exception("調用接口異常, 接口響應是result={}, 異常信息為:{}".format(result, e))
        self.logout()

    # 調用多個dubbo接口,注:確保所有接口是同一個ip和port
    def invoke_dubbo_apis(self,datas):
        summary = []
        if isinstance(datas,list):
            for i in range(len(datas)):
                result = self.invoke_dubbo_api(datas[i])
                summary.append({"data":datas[i],"result":result})
            return summary
        else:
            return "請確認入參是list"

    def logout(self):
        self.telnet_client.logout_host()

if __name__ == '__main__':
    data = {
        'dubbo_service': 'xxx.xxx.xx.xxxx.xxxx.xxxxService',
        'dubbo_method': 'xxxxx',
        'parameters': ({"id":"123456789","mobile":12456},)
    }
    i = InvokeDubboApi('127.0.0.1:110741')
    i.invoke_dubbo_api(data)
    i.logout()

 

請求結果:
在這里插入圖片描述

四、注意事項

1、請求參數

數據data中的參數字段parameters是一個元組,后面的 ‘,’ 不能少

2、請求參數異常

請求Dubbo接口如果填入的參數有誤,會報 no such method 的錯誤,請檢查一下參數是否正常

3、當要批量請求時

傳入的參數必須是list,且需要同樣的IP和端口。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM