Здравствуйте уважаемые знатоки.
Я в своих проектах когда мне нужно обеспечить взаимодействие python и nodejs приложений использую обычный http TCP (UNIX socket не подходил к сожалению в данном случае мне, поэтому использовал TCP), на локальном ip адресе 127.0.0.1. И все работает хорошо. Однако решил взглянуть в сторону Redis, подумал что если оба приложения написаные на разных языках, подключившись к Redis PUB/SUB они будут передавать друг другу сообщения гораздо быстрее чем по TCP. Но кажется я жестоко ошибся.
Итак вот результаты тестов (сам код будет ниже):
---- Redis PUB/SUB ----
10 сообщений python -> nodejs (среднее время передачи сообщений: 0.0018999814987182618)
100 сообщений python -> nodejs (среднее время передачи сообщений: 0.001810011863708496)
500 сообщений python -> nodejs (среднее время передачи сообщений: 0.006044007778167724)
1000 сообщений python -> nodejs (среднее время передачи сообщений: 0.017947996616363527)
2000 сообщений python -> nodejs (тест провален, ошибка в терминале:
libgcc_s.so.1 must be installed for pthread_cancel to work
libgcc_s.so.1 must be installed for pthread_cancel to work
Аварийный останов
)
---- TCP ----
10 сообщений python -> nodejs (среднее время передачи сообщений: 0.0032999515533447266)
100 сообщений python -> nodejs (среднее время передачи сообщений: 0.001379995346069336)
500 сообщений python -> nodejs (среднее время передачи сообщений: 0.0012699985504150391)
1000 сообщений python -> nodejs (среднее время передачи сообщений: 0.0013020012378692626)
2000 сообщений python -> nodejs (среднее время передачи сообщений: 0.0011915005445480348)
5000 сообщений python -> nodejs (среднее время передачи сообщений: 0.0010703979015350342)
10000 сообщений python -> nodejs (среднее время передачи сообщений: 0.001122001028060913)
100000 сообщений python -> nodejs (среднее время передачи сообщений: 0.0010812000036239625)
Вот так. Сколько бы сообщений не отправил по TCP , среднее время передачи 1 - 3 млс.
А теперь код который использовался в тесте. Может я что то делаю не так, почему Redis PUB/SUB хуже передает сообщения чем TCP, может что то другое посоветуете?
Код python для Redis PUB/SUB:
import sys
import time
import redis.asyncio as redis
import asyncio
connect_redis = redis.Redis(host = 'localhost', port = 6379)
count = 10
is_stop = False
if len(sys.argv) > 1:
count = int(sys.argv[1])
if len(sys.argv) > 2:
is_stop = True
async def pub_to_redis(connect_redis : object, channel : str, message : str) -> None:
sub = connect_redis.pubsub(ignore_subscribe_messages = True)
await sub.subscribe(channel)
await connect_redis.publish(channel, message)
async def ggg(connect_redis : object, count : int, is_stop : bool) -> None:
channel = 'test'
if is_stop:
await pub_to_redis(connect_redis = connect_redis, channel = channel, message = 'stop')
return
for _ in range(count):
message = str(time.time())[:14]
await pub_to_redis(connect_redis = connect_redis, channel = channel, message = message)
loop = asyncio.new_event_loop()
tasks = [
loop.create_task(ggg(connect_redis, count, is_stop)),
]
loop.run_until_complete(asyncio.wait(tasks))
Код js (nodejs) для Redis PUB/SUB:
const redis = require('redis');
(async () => {
var arr = [];
const client = redis.createClient();
const subscriber = client.duplicate();
await subscriber.connect();
await subscriber.subscribe('test', (message, channel) => {
if(message == 'stop'){
var sum = arr.reduce((a, b) => a + b, 0);
console.log('average', sum / arr.length);
console.log('count', arr.length);
arr = [];
return;
}
arr.push((+(new Date()) / 1000) - +message);
});
})();
------------------------------------------------------------
Код python для TCP:
import sys
import requests
import time
port = 12333
default_http_headers = {
'Connection':'close',
'Content-Type':'application/json'
}
count = 10
is_stop = False
if len(sys.argv) > 1:
count = int(sys.argv[1])
if len(sys.argv) > 2:
is_stop = True
if is_stop:
data = '{"request":"stop"}'
requests.post('http://127.0.0.1:'+str(port)+'/db_query', timeout = 30.0, headers = default_http_headers, data = data.encode('utf-8'))
sys.exit(0)
for _ in range(count):
data = '{"request":'+str(time.time())[:14]+'}'
requests.post('http://127.0.0.1:'+str(port)+'/db_query', timeout = 30.0, headers = default_http_headers, data = data.encode('utf-8'))
Код js (nodejs) для TCP:
const express = require('express');
const app = express();
var port = 12333;
var arr = [];
async function db_query(data){
if(data.request == 'stop'){
var sum = arr.reduce((a, b) => a + b, 0);
console.log('average', sum / arr.length);
console.log('count', arr.length);
arr = [];
return;
}
arr.push((+(new Date()) / 1000) - data.request);
}
(async () => {
app.use(express.json());
app.post('/db_query', async function (req, res) {
var result = await db_query(req.body);
res.set('Content-Type', 'application/json');
res.send(result+'\n');
});
app.listen(port, '127.0.0.1', function(){
console.log('Listening 127.0.0.1:'+port+'...');
});
})();
Для тестов Redis PUB/SUB
открываем 2 терминала на debian, в первом вставляем:
node subscriber.js
во втором:
python3 publisher.py 100
после выполнения
python3 publisher.py 0 stop
Для тестов TCP
открываем 2 терминала на debian, в первом вставляем:
node subscriber2.js
во втором:
python3 publisher2.py 100
после выполнения
python3 publisher2.py 0 stop
Вот.
Что думаете?