Quay lại

Tăng Hiệu Suất Cho Môi Trường Production Sử dụng OPcache - Laravel Chuyên mục PHP và Laravel    2024-05-27    59 Lượt xem    51 Lượt thích    comment-3 Created with Sketch Beta. 0 Bình luận

Tăng Hiệu Suất Cho Môi Trường Production Sử dụng OPcache - Laravel

Hôm nay chúng ta sẽ cùng nhau áp dụng OPcache vào dự án laravel production để giúp tăng hiệu suất, làm cho ứng dụng của chúng ta tải nhanh hơn, dưới đây là một số thông tin về nó, cho các bạn nào chưa biết về OPcache. Mình sẽ ra video để demo về thằng OPcache này!

OPcache

Nếu KHÔNG sử dụng OPCache thì lần lượt các bước mà PHP Script sẽ như sau:

  1. Đọc mã nguồn: PHP engine đọc mã nguồn từ file.

  2. Tokenization: Mã nguồn được phân tích thành các token. Đây là bước phân tích cú pháp, nơi mã nguồn được chia thành các phần tử ngữ pháp nhỏ hơn như từ khóa, biến, hằng số, toán tử, v.v. Ví dụ:

    1. <?php
      echo "Hello, World!";
      ?>
      
    2. Tokenization: `<?php`, `echo`, `"Hello`, `World!";` , `?>`
  3. Parsing: Các token được chuyển đổi thành cây cú pháp trừu tượng (Abstract Syntax Tree - AST). Cây cú pháp trừu tượng biểu diễn cấu trúc logic của mã nguồn.

  4. Biên dịch thành opcode: AST được biên dịch thành mã opcode (operation code), một tập hợp các lệnh mà máy ảo PHP (Zend Engine) có thể hiểu và thực thi.

  5. Lưu trữ trong OPcache (nếu bật): Nếu OPcache được kích hoạt, mã opcode sẽ được lưu trữ trong bộ nhớ đệm để sử dụng lại trong các lần thực thi sau. Điều này giúp giảm thời gian biên dịch cho các yêu cầu tiếp theo.

  6. Thực thi opcode: Máy ảo PHP (Zend Engine) thực thi mã opcode. Trong quá trình này, nó sẽ:

    • Thực hiện các phép toán và xử lý logic.
    • Gọi các hàm và phương thức.
    • Tương tác với cơ sở dữ liệu hoặc các hệ thống ngoại vi khác.
    • Quản lý bộ nhớ và xử lý các biến.
  7. Gửi kết quả đến máy chủ web: Kết quả của quá trình thực thi (thường là HTML) được gửi đến máy chủ web (như Apache, Nginx).

  8. Máy chủ web trả về kết quả cho client: Máy chủ web gửi phản hồi này về cho trình duyệt của người dùng.

Nếu chúng ta sử dụng OPCache:

OPcache là một phần mở rộng cho PHP nhằm tăng hiệu suất của các ứng dụng PHP. Nó hoạt động bằng cách lưu trữ mã bytecode đã được biên dịch của các tập lệnh PHP trong bộ nhớ chia sẻ (shared memory), giúp giảm thời gian thực thi mã và tài nguyên cần thiết để phân tích và biên dịch lại mã PHP mỗi khi nó được yêu cầu.

Công dụng của OPcache:

  1. Tăng tốc độ thực thi:

    • Khi một tập lệnh PHP được yêu cầu, OPcache sẽ kiểm tra xem mã bytecode đã được lưu trữ trong bộ nhớ chưa. Nếu có, mã này sẽ được thực thi ngay lập tức mà không cần phân tích và biên dịch lại. Điều này giúp giảm đáng kể thời gian thực thi.
  2. Giảm tải máy chủ:

    • Giảm số lần phân tích và biên dịch mã PHP, giúp tiết kiệm tài nguyên CPU và bộ nhớ.
  3. Tăng khả năng xử lý:

    • Các ứng dụng PHP có thể xử lý nhiều yêu cầu hơn trong cùng một khoảng thời gian vì thời gian thực thi từng yêu cầu được giảm.
  4. Giảm độ trễ phản hồi:

    • Do thời gian thực thi mã được giảm, thời gian phản hồi của ứng dụng PHP cũng nhanh hơn, cải thiện trải nghiệm người dùng.

Cách bật OPcache:

Để bật OPcache trong PHP, bạn cần thực hiện một số bước cấu hình:

  1. Cài đặt OPcache:

    • Trên các hệ thống Linux, bạn có thể cài đặt OPcache thông qua trình quản lý gói. Ví dụ, trên Ubuntu:
      sudo apt-get install php-opcache​
  2. Cấu hình OPcache:

    • Mở tệp cấu hình PHP (thường là php.ini) và thêm hoặc sửa các dòng sau:
      ; Kích hoạt OPcache
      opcache.enable=1
      
      ; Kích hoạt OPcache cho phiên bản CLI (Command Line Interface)
      opcache.enable_cli=1
      
      ; Dung lượng bộ nhớ đệm (MB)
      opcache.memory_consumption=128
      
      ; Dung lượng bộ nhớ đệm cho các string (MB)
      opcache.interned_strings_buffer=8
      
      ; Số file tối đa có thể lưu trữ trong bộ nhớ đệm
      opcache.max_accelerated_files=10000
      
      ; Thời gian kiểm tra thay đổi file (giây)
      opcache.revalidate_freq=2
      
      ; Giới hạn tối đa bộ nhớ cache bị phân mảnh (%)
      opcache.max_wasted_percentage=5
      
      ; Tự động nạp lại cache khi tỉ lệ bộ nhớ lãng phí vượt quá giới hạn
      opcache.revalidate_path=0
      
      ; Bật chế độ Fast Shutdown để cải thiện hiệu suất
      opcache.fast_shutdown=1
      
      ; Bật file cache để lưu các file opcode vào đĩa
      opcache.file_cache=/tmp
      
      ; Tăng thời gian timeout của file cache (giây)
      opcache.file_cache_only=0
      
      ; Bật tính năng bảo vệ bộ nhớ chia sẻ
      opcache.protect_memory=1
      
      ; Đặt mức độ tối ưu hóa tối đa
      opcache.optimization_level=0x7FFFBFFF
      
  3. Khởi động lại máy chủ web:

    • Sau khi cấu hình xong, khởi động lại máy chủ web của bạn (Apache, Nginx, v.v.) để áp dụng thay đổi.
      sudo systemctl restart apache2
      # hoặc
      sudo systemctl restart nginx​

Kiểm tra OPcache:

Để kiểm tra xem OPcache đã được bật và hoạt động hay chưa, bạn có thể tạo một tệp PHP với nội dung sau và truy cập nó từ trình duyệt:

<?php
   phpinfo();
?>​

Trong trang thông tin PHP được hiển thị, tìm mục "Zend OPcache" để xem các thông tin chi tiết và trạng thái của OPcache.

Laravel Docker Nginx + PHP-FPM + OPcache

Link git : Link

docker-compose.yml

version: "3.8"
services:
    api:
        container_name: api
        build:
            context: .
            target: php
            args:
                - APP_ENV=${APP_ENV}
        environment:
            - APP_ENV=${APP_ENV}
        working_dir: /var/www
        volumes:
            - ./:/var/www
        ports:
            - 9000:8080
        depends_on:
            - database
            - redis
    database:
        container_name: database
        image: mysql:8.0
        ports:
            -   3306:3306
        environment:
            - MYSQL_DATABASE=default
            - MYSQL_USER=laravel
            - MYSQL_PASSWORD=secret
            - MYSQL_ROOT_PASSWORD=secret
        volumes:
            - db-data:/var/lib/mysql
    redis:
        container_name:  redis
        image: redis:alpine
        command: redis-server --appendonly yes --requirepass  "secret"
        ports:
            - 6380:6379
volumes:
    db-data: ~

Dockerfile

# Used for prod build.
FROM php:8.1-fpm as php

# Set environment variables
ENV PHP_OPCACHE_ENABLE=1
ENV PHP_OPCACHE_ENABLE_CLI=1
ENV PHP_OPCACHE_VALIDATE_TIMESTAMPS=1
ENV PHP_OPCACHE_REVALIDATE_FREQ=1

# Install dependencies.
RUN apt-get update && apt-get install -y unzip libpq-dev libcurl4-gnutls-dev nginx libonig-dev

# Install PHP extensions.
RUN docker-php-ext-install mysqli pdo pdo_mysql bcmath curl opcache mbstring

# Copy composer executable.
COPY --from=composer:2.3.5 /usr/bin/composer /usr/bin/composer

# Copy configuration files.
COPY ./docker/php/php.ini /usr/local/etc/php/php.ini
COPY ./docker/php/php-fpm.conf /usr/local/etc/php-fpm.d/www.conf
COPY ./docker/nginx/nginx.conf /etc/nginx/nginx.conf

# Set working directory to /var/www.
WORKDIR /var/www

# Copy files from current folder to container current folder (set in workdir).
COPY --chown=www-data:www-data . .

# Create laravel caching folders.
RUN mkdir -p /var/www/storage/framework
RUN mkdir -p /var/www/storage/framework/cache
RUN mkdir -p /var/www/storage/framework/testing
RUN mkdir -p /var/www/storage/framework/sessions
RUN mkdir -p /var/www/storage/framework/views

# Fix files ownership.
RUN chown -R www-data /var/www/storage
RUN chown -R www-data /var/www/storage/framework
RUN chown -R www-data /var/www/storage/framework/sessions

# Set correct permission.
RUN chmod -R 755 /var/www/storage
RUN chmod -R 755 /var/www/storage/logs
RUN chmod -R 755 /var/www/storage/framework
RUN chmod -R 755 /var/www/storage/framework/sessions
RUN chmod -R 755 /var/www/bootstrap

# Adjust user permission & group
RUN usermod --uid 1000 www-data
RUN groupmod --gid 1001 www-data

RUN ["chmod", "+x", "docker/entrypoint.sh"]

# Run the entrypoint file.
ENTRYPOINT ["docker/entrypoint.sh" ]

docker/nginx/nginx.conf

user www-data;

events {
    worker_connections 2048;
    use epoll;
}

http {
    keepalive_timeout 500;
    keepalive_requests 5000;

    client_max_body_size 32m;
    client_body_buffer_size 32m;

    sendfile on;
    server_tokens off;

    tcp_nopush on;
    tcp_nodelay on;
    reset_timedout_connection on;

    gzip on;
    gzip_comp_level 5;
    gzip_min_length 256;
    gzip_proxied any;
    gzip_types application/javascript application/json application/xml text/css text/plain text/xml;
    gzip_vary on;

    open_file_cache max=1000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;

    upstream php-fpm {
        server 127.0.0.1:9000 max_fails=5 fail_timeout=5s;
    }

    server {
        listen 8080;
        server_name example.com;

        root /var/www/public;
        index index.php;

        error_log  /var/log/nginx/error.log;
        access_log /var/log/nginx/access.log;

        include /etc/nginx/mime.types;

        location / {
            try_files $uri $uri/ /index.php?$query_string;
        }

        location ~ \.php$ {
            fastcgi_pass php-fpm;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param SCRIPT_NAME $fastcgi_script_name;
            include fastcgi_params;
        }
    }
}

docker/nginx/php-fpm.conf

[www]

; pool name ('www' here)
[www]

; Note: This value is mandatory.
listen = 127.0.0.1:9000

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = www-data
group = www-data

; Note: This value is mandatory.
pm = dynamic

pm.max_children = 50

pm.start_servers = 2

pm.min_spare_servers = 1

pm.max_spare_servers = 3

pm.max_requests = 5000

; Default Value: not set
pm.status_path = /phpstatus

; Default Value: not set
ping.path = /phpping

; Default Value: pong
ping.response = pong

;php_admin_value[memory_limit] = 32M
php_admin_value[disable_functions] = shell_exec

docker/nginx/nginx.conf

# https://www.php.net/manual/en/opcache.configuration.php
zend_extension=opcache.so
opcache.enable=${PHP_OPCACHE_ENABLE}
opcache.enable_cli=${PHP_OPCACHE_ENABLE_CLI}
opcache.validate_timestamp=${PHP_OPCACHE_VALIDATE_TIMESTAMP}
opcache.revalidate_freq=${PHP_OPCACHE_REVALIDATE_FREQ}
opcache.memory_consumption=128

docker/nginx/entrypoint.sh

#!/bin/bash

if [ ! -f "vendor/autoload.php" ]; then
    composer install --no-progress --no-interaction
fi

if [ ! -f ".env" ]; then
    echo "Creating env file for env $APP_ENV"
    cp .env.example .env
else
    echo "env file exists."
fi

php artisan migrate
php artisan optimize clear
php artisan view:clear
php artisan route:clear

php-fpm -D
nginx -g "daemon off;"

Bình luận (0)

Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough
Michael Gough

Bài viết liên quan

Learning English Everyday