Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Menggunakan Penyelia untuk mengendalikan pelaksanaan Perintah Symfony

Menggunakan Penyelia untuk mengendalikan pelaksanaan Perintah Symfony

WBOY
WBOYasal
2024-09-07 06:34:021125semak imbas

pengenalan

Dalam siaran ini kita akan belajar cara menggunakan penyelia untuk mengendalikan pelaksanaan arahan symfony. Pada asasnya, penyelia akan membenarkan kami:

  • Automulakan arahan
  • Automulakan semula arahan
  • Nyatakan bilangan proses yang kami mahu penyelia bermula.

Masalahnya

Kadangkala kami menggunakan crontab unix untuk mengautomasikan pelaksanaan proses. Ini mungkin berkesan pada kebanyakan masa tetapi mungkin terdapat situasi yang boleh menyebabkan masalah.

Mari bayangkan kita mempunyai jadual pangkalan data yang merekodkan pemberitahuan pengguna. Jadual menyimpan maklumat berikut:

  • pengguna
  • teks
  • saluran
  • status (MENUNGGU, DIHANTAR)
  • dicipta Di
  • dikemas kiniPada

Sebaliknya, kami telah mengekodkan arahan yang pelaksanaannya mengikut langkah seterusnya:

  • Mempertanyakan pemberitahuan MENUNGGU yang terakhir
  • Gelung pemberitahuan yang ditanya dan:
    • Menghantar setiap satu kepada pengguna yang sepadan.
    • Mengemas kini status pemberitahuan daripada MENUNGGU kepada DIHANTAR

Kami menetapkan arahan ini dalam crontab linux untuk dijalankan setiap kali (1 minit, 2 minit dll). Setakat ini bagus.

Sekarang mari bayangkan bahawa proses semasa telah menanyakan 500 pemberitahuan dan apabila ia telah menghantar 400, proses baharu bermula. Ini bermakna proses baharu akan menanyakan 100 pemberitahuan yang belum dikemas kini oleh proses terakhir serta yang baharu:

Using Supervisor to handle a Symfony Command execution

Ini boleh menyebabkan 100 pemberitahuan itu dihantar dua kali kerana kedua-dua proses telah menanyakannya.

Penyelesaian

Sebagai penyelesaian, kita boleh menggunakan penyelia. Ia akan memastikan proses kami berjalan dan akan memulakannya semula apabila diperlukan. Dengan cara ini, kami hanya menyimpan satu proses dan mengelakkan pertindihan. Mari analisa bagaimana arahan itu sepatutnya kelihatan seperti:

#[AsCommand(
    name: 'app:notification'
)]
class NotificationCommand extends Command
{
    private bool $forceFinish = false;

    protected function configure(): void
    {
        $this
            ->addOption('time-limit', null, InputOption::VALUE_OPTIONAL, 'Max time alive in seconds')
            ->addOption('time-between-calls', null, InputOption::VALUE_OPTIONAL, 'Time between every loop call')

        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->forceFinish = false;
        pcntl_signal(SIGTERM, [$this, 'signalHandler']);
        pcntl_signal(SIGINT, [$this, 'signalHandler']);

        $timeLimit = $input->getOption('time-limit');
        $timeBetweenCalls = $input->getOption('time-between-calls');
        $dtMax = (new \DateTimeImmutable())->add(\DateInterval::createFromDateString("+ {$timeLimit} seconds"));

        do{
           // Here we should execute a service to query and send notifications
           // ......

           sleep($timeBetweenCalls);
           $dtCurrent = new \DateTimeImmutable();

        }while($dtCurrent < $dtMax && !$this->forceFinish);

        return Command::SUCCESS;
    }

    public function signalHandler(int $signalNumber): void
    {
        echo 'Signal catch: ' . $signalNumber . PHP_EOL;
        match ($signalNumber) {
            SIGTERM, SIGINT => $this->forceFinish = true,
            default => null
        };
    }
}

Mari terangkan arahan langkah demi langkah:

  • Kaedah konfigurasi mengisytiharkan kepada pilihan input:

    • had masa: Masa maksimum proses arahan boleh hidup. Selepas itu, ia akan selesai dan penyelia akan memulakannya semula.
    • masa-antara-panggilan: Masa untuk tidur selepas setiap lelaran gelung. Gelung memanggil perkhidmatan yang memproses pemberitahuan dan kemudian tidur pada masa tersebut.
  • Kaedah laksana berkelakuan seperti berikut:

    • Menetapkan pembolehubah kelas forceFinish kepada true
    • Menggunakan perpustakaan pnctl PHP untuk mendaftarkan kaedah signalHandler untuk mengendalikan isyarat Unix SIGTERM dan SIGINT.
    • Mendapatkan nilai pilihan input dan mengira tarikh maksimum perintah itu boleh hidup sehingga menggunakan nilai pilihan had masa.
    • Gelung do-while melaksanakan kod yang diperlukan untuk mendapatkan pemberitahuan dan menghantarnya (ia tidak diletakkan dalam arahan, sebaliknya terdapat ulasan). Kemudian, ia tidur masa yang ditetapkan oleh pilihan masa-antara-panggilan sebelum meneruskan.
    • Jika tarikh semasa (yang dikira dalam setiap lelaran gelung) adalah lebih rendah daripada tarikh maks dan forceFinish adalah palsu, gelung diteruskan. Jika tidak perintah itu tamat.
  • Fungsi signalHandler menangkap isyarat SIGTERM dan SIGINT Unix. SIGINT ialah isyarat yang dihantar apabila kita menekan Ctrl+C dan SIGTERM ialah isyarat lalai apabila kita menggunakan arahan bunuh. Apabila fungsi signalHandler mengesannya, ia menetapkan pembolehubah forceFinish kepada benar supaya, apabila gelung semasa selesai, arahan akan tamat kerana pembolehubah forceFinish ialah tidak lagi palsu. Ini membolehkan pengguna menamatkan proses tanpa perlu menunggu sehingga tarikh maksimum selesai.

Mengkonfigurasi Penyelia

Setakat ini, kami telah mencipta arahan. Kini tiba masanya untuk menyediakan penyelia supaya ia boleh mengendalikannya. Sebelum memulakan konfigurasi, kita mesti memasang penyelia. Anda boleh melakukannya dengan menjalankan arahan berikut:

sudo apt update && sudo apt install supervisor

Selepas memasang, anda boleh memastikan penyelia berjalan dengan melaksanakan arahan seterusnya:

sudo systemctl status supervisor

Fail konfigurasi penyelia diletakkan dalam folder berikut: /etc/supervisor/conf.d. Mari buat fail bernama notif.conf dan tampal kandungan berikut:

command=php <your_project_folder>/bin/console app:notifications --time-limit=120 --time-between-calls=10
user=<your_user>
numprocs=1
autostart=true
autorestart=true
process_name=%(program_name)s_%(process_num)02d

Mari terangkan setiap kunci:

  • arahan: Perintah untuk memulakan
  • pengguna: Pengguna unix yang menjalankan arahan
  • numprocs: Bilangan proses untuk dijalankan
  • autostart: Sama ada hendak autostart arahan
  • autostart: Sama ada hendak automulakan semula perintah
  • process_name: Format nama proses unix perintah.

Dengan konfigurasi ini, perintah app:notifications akan berjalan selama maksimum 120 saat dan, ia akan tidur selama 10 saat selepas setiap gelung. Selepas melepasi 120 saat atau menyimpan isyarat unix, arahan akan keluar dari gelung dan selesai. Kemudian, penyelia akan memulakannya semula.

Kesimpulan

Kami telah belajar cara menggunakan penyelia untuk memastikan arahan berjalan tanpa perlu menggunakan crontab. Ini boleh berguna apabila proses yang dilancarkan oleh crontab mungkin bertindih, menyebabkan kerosakan data.

Dalam buku terakhir yang saya tulis, saya menunjukkan cara menggunakan penyelia untuk memastikan pekerja symfony messenger berjalan. Jika anda ingin mengetahui lebih lanjut, anda boleh mencari buku di sini: Membina Api Berorientasikan Operasi menggunakan PHP dan Rangka Kerja Symfony: Panduan langkah demi langkah

Atas ialah kandungan terperinci Menggunakan Penyelia untuk mengendalikan pelaksanaan Perintah Symfony. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn