Rumah  >  Artikel  >  Operasi dan penyelenggaraan  >  Bagaimana untuk menganalisis kod sumber Arbiter gunicorn

Bagaimana untuk menganalisis kod sumber Arbiter gunicorn

PHPz
PHPzke hadapan
2023-05-12 16:28:181378semak imbas

Seperti yang dinyatakan sebelum ini, Arbiter adalah teras proses induk gunicorn. Arbiter bertanggungjawab terutamanya untuk mengurus proses pekerja, termasuk memulakan, memantau dan membunuh proses pekerja Pada masa yang sama, Arbiter juga boleh mengemas kini panas (muat semula) aplikasi aplikasi atau menaik taraf gunicorn dalam talian apabila isyarat tertentu berlaku. Kod teras Arbiter ada dalam satu fail, dan jumlah kod tidak besar Kod sumber ada di sini: https://github.com/benoitc/gunicorn.

Arbiter terutamanya mempunyai kaedah berikut:

persediaan:

Memproses item konfigurasi, yang paling penting ialah bilangan pekerja dan kerja pekerja model

init_signal

Daftar fungsi pemprosesan isyarat

handle_xxx:

Fungsi pemprosesan khusus bagi setiap isyarat

bunuh_pekerja, bunuh_pekerja:

Hantar isyarat kepada proses pekerja

spawn_workers, spawn_workers:

:

Berdasarkan bilangan pekerja dalam fail konfigurasi dan bilangan pekerja aktif pada masa ini, tentukan sama ada untuk menghentikan atau mematikan proses pekerja

reexec

:

Terima isyarat panggilan SIGUSR2, Naik Taraf gunicorn dalam talian

muat semula:

Selepas menerima panggilan SIGHUP isyarat, proses pekerja akan dimulakan berdasarkan konfigurasi baharu dan proses pekerja sebelumnya akan dimatikan

tidur

Apabila tiada pemprosesan isyarat, gunakan tamat masa pilih untuk tidur dan terjaga

bangun

Bangunkan proses dengan menulis mesej ke paip

lari

:

Gelung utama

Satu-satunya fungsi Arbiter yang sebenarnya dipanggil oleh kod lain (Application) __init__ dan kaedah jalankan, dalam satu baris kod:

Arbiter(self).run()

Diri dalam kod di atas ialah contoh Aplikasi, di mana_ _init__ memanggil persediaan untuk menetapkan item konfigurasi. Berikut ialah kod pseudo kaedah larian

def run()
    self.init_signal()
    self.LISTENERS = create_sockets(self.cfg, self.log)
    self.manage_workers()    while True:        if no signal in SIG_QUEUE
            self.sleep()        else:
            handle_signal()

Mengenai proses anak fork

proses anak fork Kod berada dalam spawn_worker, kod sumber adalah seperti berikut:


Arbiter.spawn_worker


Proses utama:

(1) Muatkan kelas_pekerja dan instantiate (lalai ialah model segerak SyncWorker) (2) Proses induk (proses induk) kembali selepas forking, dan semua logik seterusnya dijalankan dalam proses anak

(3) Panggil pekerja. init_process untuk memasuki gelung, semua saluran baharu latihan IELTS Semua kerja dalam gelung ini

(4) Selepas gelung tamat, panggil sys.exit(0)如何进行gunicorn Arbiter 源码解析

(5) Akhirnya, pada akhirnya, rekod keluar dari proses pekerja

Berikut adalah sedikit kod yang saya tulis sendiri, yang memudahkan proses garpu utama

 1 # prefork.py 2 import sys 3 import socket 4 import select 5 import os 6 import time 7   8 def do_sub_process(): 9     pid = os.fork()10     if pid < 0:11         print &#39;fork error&#39;12         sys.exit(-1)13     elif pid > 0:14         print 'fork sub process %d'  % pid15         return16  17     # must be child process18     time.sleep(1)19     print 'sub process will exit', os.getpid(), os.getppid()20     sys.exit(0)21  22 def main():23     sub_num = 224     for i in range(sub_num):25         do_sub_process()26     time.sleep(10)27     print 'main process will exit', os.getpid()28  29 if __name__ == '__main__':30     main()

Output dalam persekitaran ujian:

subproses fork 9601

subproses fork 9602


subproses akan keluar 9601 9600

subproses akan keluar 9602 9600

 proses utama akan keluar 9600

Perlu diingat bahawa talian 20 memanggil sys.exit untuk memastikan tamatnya proses anak, jika tidak gelung for dalam fungsi utama akan diteruskan, dan logik seterusnya. Komen keluar baris 19 dan jalankan semula, dan anda akan faham dengan melihat output.

Mengenai membunuh proses kanak-kanak

Proses induk membunuh proses pekerja adalah sangat mudah Ia menghantar isyarat secara langsung 🎜>

 1     def kill_worker(self, pid, sig): 2         """\ 3         Kill a worker 4  5         :attr pid: int, worker pid 6         :attr sig: `signal.SIG*` value 7          """ 8         try: 9             os.kill(pid, sig)10         except OSError as e:11             if e.errno == errno.ESRCH:12                 try:13                     worker = self.WORKERS.pop(pid)14                     worker.tmp.close()15                     self.cfg.worker_exit(self, worker)16                     return17                 except (KeyError, OSError):18                     return19             raise

Mengenai tidur dan bangun

Mari kita lihat tidur dan bangun Arbiter. Arbiter akan "tidur" apabila tiada isyarat untuk memproses Sudah tentu, ia sebenarnya tidak memanggil masa.tidur, jika tidak isyarat tidak akan diproses serta-merta apabila ia datang. Pelaksanaan di sini lebih bijak, menggunakan paip dan pilih tamat masa. Lihat sahaja kod dan anda akan tahu


        def sleep(self):        """\
        Sleep until PIPE is readable or we timeout.
        A readable PIPE means a signal occurred.        """
            ready = select.select([self.PIPE[0]], [], [], 1.0) # self.PIPE = os.pipe()
            if not ready[0]: 
                return
            while os.read(self.PIPE[0], 1):                pass


Komen dalam kod adalah sangat jelas, sama ada PIPE boleh dibaca dan dikembalikan serta-merta, atau masa tunggu habis. Paip boleh dibaca kerana isyarat berlaku. Berikut ialah lihat fungsi paip

()


Buat paip kembalikan sepasang deskriptor fail

boleh digunakan untuk membaca dan menulis, masing -masing. fungsi

        def wakeup(self):            """
            Wake up the arbiter by writing to the PIPE            """
            os.write(self.PIPE[1], b'.')

Akhir sekali pasangkan pemprosesan isyarat Arbiter
    :
  • Keluar, INT: Tutup pantas  os.pipeTERMA: Penutupan yang anggun. Menunggu pekerja menyelesaikan permintaan semasa sehingga tamat masa.

    HUP: Muat semula konfigurasi, mulakan proses pekerja baharu dengan konfigurasi baharu dan tutup proses pekerja lama dengan anggun. Gunicorn juga akan memuatkan versi baharu jika aplikasi tidak dipramuat (menggunakan pilihan --preload).

    TTIN: Tingkatkan bilangan proses sebanyak satu

    TTOU: Kurangkan bilangan proses sebanyak satu

    USR1: Buka semula fail log

    USR2: Naik taraf Gunicorn dengan pantas. Isyarat istilah yang berasingan harus digunakan untuk menamatkan proses lama. Isyarat ini juga boleh digunakan untuk menggunakan versi aplikasi baharu yang dipramuat.

    Winch: Matikan proses pekerja dengan anggun apabila Gunicorn didaemonkan.

Atas ialah kandungan terperinci Bagaimana untuk menganalisis kod sumber Arbiter gunicorn. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam