Rumah  >  Soal Jawab  >  teks badan

Cara untuk membetulkan isu 2003 (HY000): Tidak dapat menyambung ke pelayan MySQL 'db_mysql:3306' (111)

<p>Baru-baru ini saya cuba menyimpan pelayan Python FastAPI saya (juga untuk tujuan replikasi/penggandaan). Sebelum ini, saya hanya mempunyai pelayan MySQL dalam bekas Docker dan semuanya baik-baik saja, tetapi apabila saya juga menjadikan pelayan web saya sebagai perkhidmatan, ia tidak dapat menyambung ke pelayan MySQL, jadi kini aplikasi itu tidak berfungsi.</p> <p>Berikut ialah coretan kod untuk penyambung permulaan pangkalan data pelayan dalam aplikasi</p> <pre class="lang-py prettyprint-override"><kod>dari fastapi import FastAPI import mysql.connector app = FastAPI() dbconfig = { "hos": "localhost", "pangkalan data": "server_db", "pengguna": "db_user", "kata laluan": "kata laluan pengguna" } # Semak sambungan pangkalan data cuba: init_cnx = mysql.connector.connect( hos='localhost', pengguna='db_user', kata laluan='kata laluan pengguna' ) kursor = init_cnx.cursor() cursor.execute("TUNJUKKAN PANGKALAN DATA SEPERTI 'server_db'") jika cursor.fetchone() == Tiada: # Jika pangkalan data tidak wujud, buat pangkalan data cursor.execute("CIPTA PANGKALAN DATA pelayan_db") cursor.execute("GUNAKAN pelayan_db") cursor.execute("BUAT Mesej JADUAL (" "id_mesej INT BUKAN NULL AUTO_INCREMENT," "nama_pengirim VARCHAR(32)," "teks_mesej VARCHAR(64)," "dicipta_pada DATE," "pengguna_messages_count INT," "KUNCI UTAMA (message_id));") print('Pangkalan data telah dibuat!') cursor.close() init_cnx.close() kecuali mysql.connector.Error as err: print("Ralat berlaku dalam init_cnx:", err) # Fungsi I/O pangkalan data async def execute_db_query(query, cursor_buffered=False): cnx = mysql.connector.connect(**dbconfig) cuba: kursor = cnx.cursor(buffered=cursor_buffered) cursor.execute("GUNAKAN pelayan_db") cursor.execute(query) hasil = cursor.fetchall() cnx.commit() print("Pertanyaan berjaya dilaksanakan!") pulangan hasil kecuali Pengecualian sebagai e: print("Ralat semasa melaksanakan pertanyaan:", e) akhirnya: jika cnx: cnx.close() # Dapatkan fungsi direktori akar, hanya digunakan untuk menyemak sama ada aplikasi disambungkan ke pangkalan data @app.get("/") async def get_root(): cuba: entries_count = tunggu execute_db_query("PILIH COUNT(*) DARI Messages", cursor_buffered=True) kembalikan {"Entri mesej": entries_count[0][0]} kecuali Pengecualian sebagai e: kembalikan {"Ralat": e} </code></pre> <p>Fail Docker Pelayan</p> <pre class="brush:php;toolbar:false;">FROM python:3.11.4-slim-bookworm WORKDIR/apl SALINAN keperluan.txt . RUN pip install --no-cache-dir -r requirements.txt COPY server.py . DEDAH 8000 CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]</pre> <p>skrip init.sql</p> <pre class="lang-sql prettyprint-override"><kod>BUAT PENGGUNA 'db_user'@'%' DIKENAL PASTI OLEH 'kata laluan pengguna'; BERIKAN SEMUA KEISTIMEWAAN PADA *.* KEPADA 'db_user'@'%' DENGAN PILIHAN GERAN; KEISTIMEWAAN FLUSH; </code></pre> <p>dan docker-compose.yml</p> <pre class="lang-yaml prettyprint-override"><code>versi: "3.8" perkhidmatan: db_mysql: imej: mysql:8 mulakan semula: sentiasa persekitaran: MYSQL_ROOT_PASSWORD: "root" jilid: - "./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql" - "./mysql/db_mysql_data:/var/lib/mysql" - "./mysql/mysql_logs:/var/log/mysql" rangkaian: -dummy_network pelayan_1: imej: dummy_msg_server pelabuhan: - "8081:8000" rangkaian: -dummy_network #perintah: sh -c "tidur 60-an" bergantung kepada: -db_mysql pelayan_2: imej: dummy_msg_server pelabuhan: - "8082:8000" rangkaian: - dummy_network #perintah: sh -c "tidur 60-an" bergantung kepada: -db_mysql jilid: db_mysql_data: #external: true rangkaian: dummy_network: pemandu:jambatan </code></pre> <p>Walaupun cuba menggunakan API sebelum bekas MySQL telah dimulakan sepenuhnya mungkin mengakibatkan ralat, ini tidak menjadi masalah kerana saya menunggu sehingga pelayan MySQL menunjukkan ia bersedia untuk mengendalikan permintaan. Selain itu, saya tidak cuba menyambung ke pelayan MySQL. </p> <p>Saya cuba menyambung menggunakan nama hos/alamat IP. Cuba tukar imej python:3.11.4 dalam fail docker kepada versi debian yang lebih awal dan tidak menggunakan imej tipis.Cuba gunakan rangkaian awam secara eksplisit untuk bekas. Docker terus menunjukkan bahawa bekas itu berada dalam rangkaian, dan permintaan curl daripada bekas pelayan mengembalikan sesuatu. Selain itu, docker-compose.yml sebelum ini menyediakan port 3306:3306 untuk perkhidmatan db_mysql. Rasanya itu bukan masalah juga. </p> <p><strong>Kemas kini 1. </strong>Semasa penyiasatan, didapati bahawa jika pangkalan data telah dibuat, aplikasi tidak mempunyai masalah menghantar permintaan kepadanya dan mendapat respons yang betul. Satu-satunya masalah dengannya ialah pangkalan data tidak boleh dibuat menggunakan skrip cipta dalam kod. </p><p> (Rasanya, saya patut mengemas kini blok kod kerana projek itu dalam fasa lain sekarang.)</p>
P粉178132828P粉178132828431 hari yang lalu714

membalas semua(1)saya akan balas

  • P粉141455512

    P粉1414555122023-09-06 09:54:17

    Saya menghadapi masalah di mana pelayan dan bekas pangkalan data dimulakan pada masa yang sama, menyebabkan masalah. Percubaan pertama (dan terakhir) untuk menyambung ke pelayan pangkalan data berlaku sebelum pelayan pangkalan data bersedia untuk menerima sambungan.

    Untuk menyelesaikan masalah ini, saya memutuskan untuk menambah pemeriksaan kesihatan dalam fail docker-compose.yml:

    version: "3.8"
    services:
      db_mysql:
        image: mysql:8
        restart: always
        ports:
          - 3306:3306
        environment:
          MYSQL_ROOT_PASSWORD: "root"
        volumes:
          - "./mysql/init.sql:/docker-entrypoint-initdb.d/init.sql"
          - "./mysql/db_mysql_data:/var/lib/mysql"
          - "./mysql/mysql_logs:/var/log/mysql"
        healthcheck:
          test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-uroot", "-proot"]
          timeout: 1s
          interval: 40s
          retries: 5
    
      server_1:
        build:
          context: .
          dockerfile: Dockerfile
        restart: always
        ports:
          - "8081:8000"
        depends_on:
          db_mysql:
            condition: service_healthy
    
      server_2:
        build:
          context: .
          dockerfile: Dockerfile
        restart: always
        ports:
          - "8082:8000"
        depends_on:
          db_mysql:
            condition: service_healthy
    
    volumes:
      db_mysql_data: #external: true
    

    Dengan konfigurasi ini, bekas pelayan tidak akan bermula sehingga pemeriksaan kesihatan mengesahkan bahawa pelayan pangkalan data sudah sedia.

    Walau bagaimanapun, terdapat cara yang lebih baik untuk mengendalikan situasi ini, yang melibatkan penggunaan skrip wait-for-it.sh. Saya secara peribadi mengenali beberapa pembangun bahagian belakang berpengalaman yang juga menggunakan bekas Docker untuk memisahkan aplikasi mereka kepada perkhidmatan mikro. Mereka menyatakan komen positif tentang penggunaan skrip ini. Walaupun saya belum mencubanya secara peribadi, saya mengesyorkan mempertimbangkannya sebagai penyelesaian alternatif.

    balas
    0
  • Batalbalas