Python ソケットと Kafka はメッセージを送受信します

初期化.py

import logging

import socketio
from flask import Flask, request
from flask_appbuilder import AppBuilder, SQLA
from flask_cors import CORS
from flask_redis import FlaskRedis
from flask_ckeditor import CKEditor
from flask_socketio import SocketIO, emit

from .models import RDMessage
from .myKafka.myKafkaManager import myKafkaManager

"""
 Logging configuration
"""

logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
logging.getLogger().setLevel(logging.DEBUG)

app = Flask(__name__)
app.config.from_object("config")
# CORS(app, supports_credentials=True)
CORS(app, resources={
    
    r"/*": {
    
    "origins": "*"}})
db = SQLA(app)
async_mode = 'threading'
kafkaList = app.config.get('KAFKALIST')
# print('kafkaList', kafkaList)
#url = "kafka://{}".format(kafkaList[0])
url = ["kafka://{}".format(i) for i in kafkaList]
# socketioApp = socketio.Server(async_mode=async_mode, cors_allowed_origins='*', client_manager=socketio.KafkaManager(url))
# app.wsgi_app = socketio.WSGIApp(socketioApp, app.wsgi_app)
socketioApp =SocketIO(app, async_mode=async_mode, cors_allowed_origins='*')
mgr = None
sio = None
if len(kafkaList)>0:
    # mgr = socketio.KafkaManager(url)
    mgr = myKafkaManager(url)
    # socketioApp = SocketIO(app, async_mode=async_mode, cors_allowed_origins='*', client_manager=mgr)
    socketioApp = socketio.Server(async_mode=async_mode, cors_allowed_origins='*', client_manager=mgr)

app.wsgi_app = socketio.WSGIApp(socketioApp, app.wsgi_app)


# mgr = socketio.KafkaManager(url)
# sio = socketio.Server(client_manager=mgr)
# app.wsgi_app = socketio.WSGIApp(sio, app.wsgi_app)

# send CORS headers 2022-4-18 10:48:41
@app.after_request
def after_request(response):
    print('request.url====', request.url)
    response.headers.add('Access-Control-Allow-Origin', '*')
    if request.method == 'OPTIONS':
        response.headers['Access-Control-Allow-Methods'] = '*'
        headers = request.headers.get('Access-Control-Request-Headers')
        if headers:
            response.headers['Access-Control-Allow-Headers'] = headers
            ##response.headers['Authorization'] = 'xiaominggessdfs3432ds34ds32432cedsad332e23'
    return response

redis_store = FlaskRedis()
redis_store.init_app(app)

ckeditor = CKEditor()
ckeditor.init_app(app)
base_template = "app/base.html"
appbuilder = AppBuilder(app, db.session, base_template=base_template)


"""
from sqlalchemy.engine import Engine
from sqlalchemy import event

#Only include this for SQLLite constraints
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
    # Will force sqllite contraint foreign keys
    cursor = dbapi_connection.cursor()
    cursor.execute("PRAGMA foreign_keys=ON")
    cursor.close()
"""

from . import views
# from app.view import myEvent
from app.view import mydemo
if len(kafkaList)>0:
    from app.view import myKafkaEvent
else:
    from app.view import myEvent

mydemo.py

from flask import request, current_app, send_from_directory, render_template
from flask_appbuilder import BaseView, expose

from app import appbuilder


class MyDemoView(BaseView):
    route_base = "/mydemo"

    @expose( '/index', methods = ['GET'] )
    def index(self):
        return render_template('myTemp/myDemo/index.html')

appbuilder.add_view_no_menu(MyDemoView())

myKafkaEvent.py

import datetime
import json
import uuid
from threading import Lock

import socketio

from app import socketioApp, mgr, appbuilder
from app.common.function import sendShortMessageFun
from app.models import RDMessage
from app.myKafka.myKafkaConsumer import background_thread
from app.view.common import addRDMessage

@socketioApp.event
def connect(sid, environ):
    print('socketioApp connect ', sid, environ)

@socketioApp.event
def my_message(sid, data):
    print('socketioApp message ', sid, data)

@socketioApp.event
def disconnect(sid):
    print('socketioApp disconnect ', sid)

@socketioApp.on('*')
def catch_all(event, sid, data):
    print("服务器已经接收到消息 catch_all :", event, sid, data)
    if isinstance(data, dict):
        mqtt_msg = data
    else:
        mqtt_msg = json.loads(data)
    topic = event
    print("服务器已经接收到消息:", topic, mqtt_msg)
    if topic in ["message"]:
        mqtt_msg['msg'] = '服务器已经接收到消息'
        socketioApp.emit("response", mqtt_msg)

    if topic in ["demo1"]:
        socketioApp.emit("response", mqtt_msg)


myEvent.py

import datetime
import json
import uuid
from threading import Lock

import socketio
from flask import current_app
from flask_socketio import emit
from kafka import KafkaConsumer

from app import socketioApp, appbuilder
from app.common.function import sendShortMessageFun
from app.models import RDMessage
from app.view.common import addRDMessage

thread = None
thread_lock = Lock()
consumer = None

@socketioApp.event
def connect():
    # print('socketioApp connect ', sid, environ)
    kafkaList = current_app.config.get('KAFKALIST')
    print('kafkaList', kafkaList)
    # 这个方式失败,看到了kafka 消息,就看不到socket 消息
    # if len(kafkaList) > 0:
    #     consumer = KafkaConsumer(bootstrap_servers=kafkaList)
    #     topics = get_topics(consumer)
    #     consumer.subscribe([i for i in topics])  # 消费者订阅多个topic
    # global thread
    # with thread_lock:
    #     if thread is None:
    #         socketioApp.sleep(1)
    #         thread = socketioApp.start_background_task(target=background_thread1(consumer))
    print("服务器已经接收到消息 connect:", kafkaList, thread)

@socketioApp.on("message")
def handle_event_message(message):
    print("服务器已经接收到消息:", message)
    message['msg'] = '服务器已经接收到消息'
    emit("response", message)

@socketioApp.event
def connect_error(sid):
    print("The connection failed!", sid)

@socketioApp.event
def disconnect(sid):
    print("I'm disconnected!", sid)



@socketioApp.on("demo1", namespace='/')
def handle_event_send(message):
    print("服务器已经接收到消息 demo1 :", message)
    if isinstance(message, dict):
        mqtt_msg = message
    else:
        mqtt_msg = json.loads(message)    
    emit("response", mqtt_msg)




myKafkaManager.pyをハイライトします。

import datetime
import json
import pickle
import uuid

from app.view.common import addRDMessage

try:
    import kafka
except ImportError:
    kafka = None
from kafka import KafkaConsumer
from socketio import KafkaManager

class myKafkaManager(KafkaManager):

    name = 'kafka'

    def __init__(self, url='kafka://localhost:9092', channel='socketio',
                 write_only=False):
        if kafka is None:
            raise RuntimeError('kafka-python package is not installed '
                               '(Run "pip install kafka-python" in your '
                               'virtualenv).')

        super(KafkaManager, self).__init__(channel=channel,
                                           write_only=write_only)

        urls = [url] if isinstance(url, str) else url
        self.kafka_urls = [url[8:] if url != 'kafka://' else 'localhost:9092'
                           for url in urls]
        self.producer = kafka.KafkaProducer(bootstrap_servers=self.kafka_urls)
        self.consumer = kafka.KafkaConsumer(self.channel,
                                            bootstrap_servers=self.kafka_urls)
        self._get_topics()
        print('__init__', self.topics, self.channel)
        topics = [i for i in self.topics]
        topics.append(self.channel)
        self.consumerAll = kafka.KafkaConsumer(bootstrap_servers=self.kafka_urls)
        self.consumerAll.subscribe(topics)  # 消费者订阅多个topic

    def _publish(self, data):
        self.producer.send(self.channel, value=pickle.dumps(data))
        self.producer.flush()

    def _kafka_listen(self):
        for message in self.consumer:
            yield message

    def _listen(self):
        for message in self._kafka_listen():
            if message.topic == self.channel:
                yield pickle.loads(message.value)

    def _get_topics(self):
        self.topics = self.consumer.topics()

    def _kafka_listen_all(self):
        print('_kafka_listen_all', self.topics, self.channel)
        for message in self.consumerAll:
            yield message

    def _listen_all(self):
        for message in self._kafka_listen_all():
            if message.topic == self.channel:
                yield pickle.loads(message.value)
            if message.topic in ["demo1", "demo2"]:
                if isinstance(message.value, bytes):
                    try:
                        res = {
    
    }
                        res['method'] = 'emit'
                        res['namespace'] = list(self.get_namespaces())[0]
                        res['room'] = None
                        res['skip_sid'] = None
                        res['callback'] = None
                        res['host_id'] = self.host_id
                        res['event'] = message.topic
                        msg = json.loads(message.value.decode("utf-8"))
                        res['data'] = msg
                    except:
                        pass
                yield res


    def _thread(self):
        for message in self._listen_all():
            data = None
            if isinstance(message, dict):
                data = message
            else:
                if isinstance(message, bytes):  # pragma: no cover
                    try:
                        data = pickle.loads(message)
                    except:
                        pass
                if data is None:
                    try:
                        data = json.loads(message)
                    except:
                        pass
            if data and 'method' in data:
                self._get_logger().info('pubsub message: {}'.format(
                    data['method']))
                try:
                    if data['method'] == 'emit':
                        self._handle_emit(data)
                    elif data['method'] == 'callback':
                        self._handle_callback(data)
                    elif data['method'] == 'disconnect':
                        self._handle_disconnect(data)
                    elif data['method'] == 'close_room':
                        self._handle_close_room(data)
                except:
                    self.server.logger.exception(
                        'Unknown error in pubsub listening thread')

Kafka_Producer.py
が Kafka メッセージ テストを送信します

# kafka_producer.py
import json
import time

from kafka import KafkaProducer, KafkaConsumer
from time import sleep

kafkaList = ['192.168.6.15:9092', '192.168.6.21:9092', '192.168.6.26:9092']
def start_producer1():
    producer = KafkaProducer(bootstrap_servers=kafkaList[0], value_serializer=lambda m:json.dumps(m).encode("utf-8"))
    for i in range(0, 1000):
        msg = 'msg is ' + str(i)
        future = producer.send('BDLY_TERMINAL_MSG_2.1', msg.encode('utf-8'))
        try:
            future.get(timeout=10)
            # 监控是否发送成功
        except Exception as e:
            print(str(e))
        sleep(3)

def start_producer(topic):
    print(topic)
    producer = KafkaProducer(bootstrap_servers=kafkaList, key_serializer=lambda k: json.dumps(k).encode(), value_serializer=lambda v: json.dumps(v).encode(), api_version=(0, 1, 0))
    for i in range(0, 3):        
        # 获得当前时间时间戳
        now = int(time.time())
        # 转换为其他日期格式,如:"%Y-%m-%d %H:%M:%S"
        timeStruct = time.localtime(now)
        strTime = time.strftime("%Y-%m-%d %H:%M:%S", timeStruct)
        msg = {
    
    }
        msg['code'] = 0    
        msg['data'] = {
    
    }
        msg['data']['user_form'] = 888888
        msg['data']['user_to'] = 888899
        msg['data']['content'] = strTime
        msg['data']['msgType'] = "1"
        msg['data']['sendTime'] = int(time.time()*1000)
        
        print(msg)
        # 同一个key值,会被送至同一个分区
        future = producer.send(topic, msg, key=msg['userId'])
        try:
            future.get(timeout=10)
            # 监控是否发送成功
        except Exception as e:
            print(str(e))
        sleep(3)

def get_topics():
    consumer = KafkaConsumer(group_id='test', bootstrap_servers=kafkaList)
    topics = consumer.topics()
    print(topics)
    return topics

if __name__ == '__main__':
    topics = get_topics()
    # topic = 'demo2'
    topic = 'demo1'
    start_producer(topic)
    print('success')

インデックス.html

<html>
    <head>
        <script type="text/javascript"
        src="https://code.jquery.com/jquery-3.4.0.min.js"></script>
        <script crossorigin="anonymous" integrity="sha512-74AKPNm8Tfd5E9c4otg7XNkIVfIe5ynON7wehpX/9Tv5VYcZvXZBAlcgOAjLHg6HeWyLujisAnle6+iKnyWd9Q==" src="https://lib.baomitu.com/socket.io/4.0.0/socket.io.js"></script>

    </head>

    <body>
        <h1>socket</h1>
        <input type="text" name="topic" id="topic" value="send_BDLY_TERMINAL_MSG_4.0">
        <input type="text" name="sendUserId" id="sendUserId" value="378191">
        <input type="text" name="message" id="message">
        <input type="button" name="" id="push" value="发送">
        <div id="log"></div>


        <script type="text/javascript" charset="utf-8">
            $(document).ready(function () {
      
      
                var namespace = ""
                //'http://' + document.domain + ':' + location.port + namespace
                var url = 'http://' + document.domain + ':' + location.port + namespace
                var socket = io.connect(url);
                // 测试消息
                socket.emit("message", {
      
       "data": url });

                socket.on('connect', function (data) {
      
      
                    console.log('connect',url)
                    socket.emit('message', {
      
       'data': 'I\'m connected!' });
                });

                socket.on('disconnect', function(data){
      
      
                    socket.emit('message', {
      
       'data': 'I\'m disconnected!' });
                });

                socket.on('response', function (data) {
      
      
                    console.log('response',data)
                });
   
                $("#push").click(function(){
      
      
                    var topic=$("#topic").val();
                    var msg = $("#message").val();
                    var sendUserId = $("#sendUserId").val();
                    //message='发送内容:'+$("#message").val()+'=====发送时间:'+gettime();
                    var message={
      
      };
                    message['sendUserId']=sendUserId;
                    message['content']=msg;
                    socket.emit(topic, message);
                })
            });
        </script>
    </body>
</html>

参考ドキュメント
https://python-socketio.readthedocs.io/en/latest/intro.html

おすすめ

転載: blog.csdn.net/lizhihua0625/article/details/124905180