Làm cách nào để chia tỷ lệ php5 + MySQL trên 200 yêu cầu / giây?


16

Tôi đang điều chỉnh trang chủ của mình để thực hiện, hiện tại nó xử lý khoảng 200 yêu cầu / giây trên 3.14.by trong đó có 6 truy vấn SQL và 20 req / giây trên 3.14.by/forum là diễn đàn phpBB.

Thật kỳ lạ, con số gần giống nhau trên một số VPS và máy chủ Atom 330 chuyên dụng.

Phần mềm máy chủ như sau: Apache2 + mod_php prefork 4 con (đã thử các số khác nhau ở đây), php5, APC, nginx, memcached để lưu trữ phiên PHP.

MySQL được cấu hình để ăn khoảng 30% RAM có sẵn (~ 150Mb trên VPS, 700Mb trên máy chủ chuyên dụng)

Điều này có vẻ như có một nút cổ chai ở đâu đó không cho phép tôi đi lên cao hơn, có gợi ý nào không? (tức là tôi biết rằng làm ít hơn 6 SQL sẽ làm cho nó nhanh hơn, nhưng điều này không giống như một yếu tố hạn chế, vì sqld ăn không quá vài% trong các truy vấn được lưu trong bộ nhớ cache)

Có ai đã thử nghiệm rằng đá apache2 đã được làm sẵn và chỉ để nginx + php nhanh hơn nhiều chưa?

Một số điểm chuẩn khác

Small 40-byte static file: 1484 r/s via nginx+apache2, 2452 if we talk to apache2 directly. 
Small "Hello world" php script: 458 r/s via ngin+apache2.

Cập nhật: Có vẻ như nút cổ chai là hiệu năng của MySQL trên dữ liệu được lưu trữ. Trang có SQL duy nhất hiển thị 354req / giây, với 6 SQL - 180 req / giây. Bạn nghĩ gì tôi có thể điều chỉnh ở đây? (Tôi có thể bỏ ra 100-200Mb cho MySQL)

[client]
port        = 3306
socket      = /var/run/mysqld/mysqld.sock

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0

[mysqld]
default-character-set=cp1251
collation-server=cp1251_general_cs

skip-character-set-client-handshake

user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /var/lib/mysql
tmpdir      = /tmp
skip-external-locking

bind-address        = 127.0.0.1

key_buffer      = 16M
max_allowed_packet  = 8M
thread_stack        = 64K
thread_cache_size   = 16
sort_buffer_size    = 8M
read_buffer_size    = 1M

myisam-recover      = BACKUP
max_connections        = 650
table_cache            = 256
thread_concurrency     = 10

query_cache_limit       = 1M
query_cache_size        = 16M

expire_logs_days    = 10
max_binlog_size         = 100M

[mysqldump]
quick
quote-names
max_allowed_packet  = 8M

[mysql]
[isamchk]
key_buffer      = 8M

!includedir /etc/mysql/conf.d/

Tại sao bạn sử dụng cả Apache và nginx?
jamieb

Đó là cấu hình phổ biến, Apache2 sang PHP và các ứng dụng khác nhau yêu cầu cơ sở hạ tầng apache, nginx để giảm dung lượng bộ nhớ apache2 khi tải.
BarsMonster

Thật ra, tôi không hiểu vấn đề của bạn. Trang web của bạn hiện đang chậm? Nếu vậy, làm thế nào là chậm? Và bạn muốn tăng tốc nó lên bao nhiêu? Bạn đã cố gắng để hồ sơ bất kỳ phần nào của trang web của bạn để xác định nơi tắc nghẽn là ở đâu?
jamieb

Nó nằm trong phần mô tả: Bây giờ là 180-200 yêu cầu / giây. Mặc dù điều này là quá đủ cho một trang chủ, tôi muốn điều chỉnh thiết lập này để các trang web khác được xây dựng trên cùng một cơ sở mã hoạt động nhanh hơn. Lý tưởng nhất là tôi muốn bão hòa kết nối 100Mbit với các trang động :-)
BarsMonster

2
"Yêu cầu mỗi giây" không thực sự là một số liệu có ý nghĩa trong bối cảnh này. Netbook của tôi có thể xử lý "200 yêu cầu mỗi giây". Bạn cần cho chúng tôi biết thời gian phản hồi mà bạn muốn đạt được theo tỷ lệ kết nối đó.
jamieb

Câu trả lời:


29

Rõ ràng, có rất nhiều bạn có thể thử. Đặt cược tốt nhất của bạn là theo đuổi nhật ký của bạn cho các truy vấn không sử dụng chỉ mục (bật nhật ký cho những truy vấn đó) và các truy vấn không được tối ưu hóa khác. Tôi đã biên soạn một danh sách lớn các tùy chọn liên quan đến hiệu suất trong những năm qua, vì vậy tôi đã bao gồm một tập hợp con nhỏ ở đây cho thông tin của bạn - hy vọng nó sẽ giúp ích. Dưới đây là một số lưu ý chung cho những thứ bạn có thể thử (nếu bạn chưa có):

MySQL

  • query_cache_type = 1 - bộ đệm truy vấn SQL được bật. Nếu được đặt thành 2, các truy vấn chỉ được lưu trong bộ nhớ cache nếu gợi ý SQL_CACHE được truyền cho chúng. Tương tự với loại 1, bạn có thể tắt bộ đệm cho một truy vấn cụ thể với gợi ý SQL_NO_CACHE
  • key_buffer_size = 128M (mặc định: 8M) - bộ nhớ đệm cho các chỉ mục bảng MyISAM. Trên các máy chủ chuyên dụng, hãy đặt mục tiêu đặt key_buffer_size thành ít nhất một phần tư, nhưng không quá một nửa, trong tổng số lượng bộ nhớ trên máy chủ
  • query_cache_size = 64M (mặc định: 0) - kích thước của bộ đệm truy vấn
  • back_log = 100 (mặc định: 50, tối đa: 65535) - Hàng đợi của các yêu cầu kết nối chưa xử lý. Chỉ quan trọng khi có nhiều kết nối trong thời gian ngắn
  • jo_buffer_size = 1M (mặc định: 131072) - bộ đệm được sử dụng khi quét toàn bộ bảng (không có chỉ mục)
  • table_cache = 2048 (mặc định: 256) - phải là max_user_connections nhân với số lượng THAM GIA tối đa mà truy vấn SQL nặng nhất của bạn chứa. Sử dụng biến "open_tables" vào thời gian cao điểm làm hướng dẫn. Ngoài ra, hãy xem biến "open_tables" - nó phải gần với "open_tables"
  • query_prealloc_size = 32K (mặc định: 8K) - bộ nhớ liên tục để phân tích cú pháp và thực thi. Tăng nếu có các truy vấn phức tạp
  • sort_buffer_size = 16M (mặc định: 2M) - giúp sắp xếp (các thao tác ORDER BY và GROUP BY)
  • read_buffer_size = 2M (mặc định: 128K) - Giúp quét liên tiếp. Tăng nếu có nhiều lần quét liên tiếp.
  • read_rnd_buffer_size = 4M - giúp bảng MyISAM tăng tốc độ đọc sau khi sắp xếp
  • max_length_for_sort_data - kích thước hàng để lưu trữ thay vì con trỏ hàng trong tệp sắp xếp. Có thể tránh đọc bảng ngẫu nhiên
  • key_cache_age_thr Ngưỡng = 3000 (mặc định: 300) - thời gian để giữ bộ đệm chính trong vùng nóng (trước khi hạ cấp xuống ấm)
  • key_cache_division_limit = 50 (mặc định: 100) - cho phép cơ chế đuổi bộ nhớ cache tinh vi hơn (hai cấp độ). Biểu thị tỷ lệ phần trăm để giữ cho mức dưới cùng. delay_key_write = ALL - bộ đệm chính không được xóa cho bảng trên mỗi bản cập nhật chỉ mục, mà chỉ khi đóng bảng. Điều này tăng tốc độ ghi trên các phím rất nhiều, nhưng nếu bạn sử dụng tính năng này, bạn nên thêm kiểm tra tự động tất cả các bảng MyISAM bằng cách khởi động máy chủ với tùy chọn --myisam-recovery = BACKUP, FORCE
  • memlock = 1 - quá trình khóa trong bộ nhớ (để giảm trao đổi trong / ngoài)

Apache

  • thay đổi phương thức sinh sản (ví dụ như mpm)
  • vô hiệu hóa nhật ký nếu có thể
  • AllowOverride Không - bất cứ khi nào có thể vô hiệu hóa .htaccess. Nó dừng apache vì tìm kiếm tệp .htaccess nếu chúng không được sử dụng để nó lưu yêu cầu tra cứu tệp
  • SendBufferSize - Đặt thành mặc định của hệ điều hành. Trên các mạng bị nghẽn, bạn nên đặt tham số này gần với kích thước của tệp lớn nhất thường được tải xuống
  • KeepAlive Off (bật mặc định) - và cài đặt lingerd để đóng các kết nối mạng đúng cách và nhanh hơn
  • Directory Index index.php - Giữ danh sách tệp càng ngắn và tuyệt đối càng tốt.
  • Tùy chọn FollowSymLinks - để đơn giản hóa quy trình truy cập tệp trong Apache
  • Tránh sử dụng mod_rewrite hoặc ít nhất là regex phức tạp
  • ServerToken = prod

PHP

  • biến_order = "GPCS" (Nếu bạn không cần biến môi trường)
  • register_globals = Tắt - ngoài việc là một rủi ro bảo mật, nó còn có tác động hiệu suất
  • Giữ include_path tối thiểu nhất có thể (tránh tra cứu thêm hệ thống tập tin)
  • display_errors = Tắt - Tắt hiển thị lỗi. Rất khuyến khích cho tất cả các máy chủ sản xuất (không hiển thị thông báo lỗi xấu trong trường hợp có vấn đề).
  • magic_quotes_gpc = Tắt
  • Magic_quotes _ * = Tắt
  • output_buffering = Bật
  • Vô hiệu hóa đăng nhập nếu có thể
  • expose_php = Tắt
  • register_argc_argv = Tắt
  • always_population_raw_post_data = Tắt
  • đặt tập tin php.ini nơi php sẽ tìm nó trước.
  • session.gc_divisor = 1000 hoặc 10000
  • session.save_path = "N; / path" - Đối với các trang web lớn, hãy xem xét sử dụng nó. Chia tệp phiên thành các thư mục con

Tinh chỉnh hệ điều hành

  • Gắn các đĩa cứng đã sử dụng với tùy chọn -o noatime (không có thời gian truy cập). Đồng thời thêm tùy chọn này vào tập tin / etc / fstab.
  • Tinh chỉnh / Proc / sys / vm / swappiness (từ 0 đến 100) để xem những gì có kết quả tốt nhất
  • Sử dụng Đĩa RAM - mount --bind -ttmpfs / tmp / tmp

Đó là danh sách hay, tôi đã có phần lớn trong số này và khi tôi thêm những thứ còn lại, hiệu suất không tăng. Có vẻ như nút cổ chai nằm ở đâu đó giữa PHP và MySQL không thể xử lý hơn 800 yêu cầu mỗi giây từ bộ đệm truy vấn ...
BarsMonster

Ok, làm thế nào để bạn kết nối với cơ sở dữ liệu (mysql_pconnect () thay vì mysql_connect ())? Bạn có sử dụng kết nối liên tục? thử cả hai cách ...
Ivan Peevski

Tôi đã kết nối và kết nối kết nối được bật trong php.ini ...: -S
BarsMonster

Chỉ cần hoàn thành, tôi sẽ thử kết nối. Tôi đã thấy các trường hợp (đặc biệt là trong thử nghiệm tải), nơi hoạt động tốt hơn.
Ivan Peevski

1

Nếu nút cổ chai không phải là CPU, thì IO của nó - mạng hoặc đĩa. Vì vậy, .. bạn cần phải xem IO đang diễn ra như thế nào. Tôi sẽ không nghĩ mạng của nó (trừ khi bạn đang sử dụng liên kết bán song công 10mbps, nhưng đáng để kiểm tra công tắc trong trường hợp tự động phát hiện không hoạt động đúng).

Rời khỏi đĩa IO, có thể là một yếu tố lớn đặc biệt là trên VPS. Sử dụng sar hoặc iostat để xem các đĩa, sau đó google cách tìm thêm chi tiết nếu đĩa của bạn đang được sử dụng nhiều.


Có, Mạng không phải là vấn đề - khi chạy ab từ máy chủ cục bộ, hiệu suất chỉ như nhau. Tôi đã kiểm tra thời gian iowait - dưới 0,01% - về cơ bản mọi thứ đều nằm trong bộ đệm của đĩa và không có ghi đĩa nào liên quan đến yêu cầu xử lý (tất cả các nhật ký đều bị tắt).
BarsMonster

1

Tôi sẽ xem xét bộ nhớ đệm với Nginx ( memcached ) hoặc Varnish .

Ít nhất bạn nên lưu trữ các tệp tĩnh với Nginx như SaveTheRbtz đã nói.


Đây là những trang động, vì vậy tôi không muốn lưu trữ chúng.
BarsMonster

1
memcached không phải là một ứng dụng bộ nhớ đệm truyền thống và có thể làm việc kỳ diệu cho các trang động. Nó nằm giữa DB và ứng dụng của bạn. Trước tiên, ứng dụng của bạn truy vấn memcached cho một đối tượng, nếu nó không ở đó, thì nó được tải từ DB. Hiệu quả thực tế là bạn đang sử dụng RAM để phục vụ các yêu cầu DB của mình thay vì lưu trữ liên tục chậm hơn nhiều trên DB.
jamieb

Memcache có thể được sử dụng với nginx, đó là tính năng được biết đến. Dung lượng lưu trữ liên tục chậm hơn không được sử dụng, tất cả nằm trong bộ đệm truy vấn trong MySQL.
BarsMonster

Bộ nhớ cache truy vấn của Memcached và MySQL không thực sự có thể so sánh được; họ thậm chí không làm điều tương tự. Bạn khá nhanh chóng để bắn hạ khá nhiều lời đề nghị được đăng ở đây mà không cần phải hiểu chúng. Tôi khuyên bạn nên cởi mở hơn một chút.
jamieb

Tôi hiểu rõ sự khác biệt giữa bộ nhớ cache truy vấn memcached và MySQL. Nhưng do thực tế là mọi thứ đều nằm trong Bộ đệm truy vấn với tỷ lệ truy cập 100%, tôi sẽ không gọi đó là "lưu trữ liên tục chậm". Câu trả lời ban đầu của ngày hôm qua là về việc sử dụng NginX + Memcached, đây là tình huống khá phổ biến để lưu trữ toàn bộ trang. Bộ nhớ đệm các đối tượng là một kịch bản khác, hoàn toàn khác. Trong khi sử dụng memcached trước MySQL là trên bàn, tôi nghĩ đến việc lấy thêm nước trái cây mà không cần đến bây giờ (vì nó sẽ yêu cầu khá nhiều thay đổi mã).
BarsMonster

1

Vì máy chủ dường như không có vấn đề gì, có lẽ trình tạo tải là vậy. Hãy thử chạy nó trên một số máy.


Hiệu suất là như nhau ngay cả khi tôi chạy nó từ chính máy chủ. Bất kể kết nối đồng thời manu như thế nào - 10 hoặc 50. Kiểm tra tải được thực hiện thông qua ab -c 10 -t 10
BarsMonster

1

Tôi nghe có vẻ như bạn có thể đạt được số lượng kết nối tối đa mà Apache cho phép. Hãy xem cấu hình Apache của bạn. Tăng giới hạn máy chủ và máy khách tối đa sẽ giúp ích nếu bạn chưa bị ràng buộc bởi một số giới hạn khác như I / O hoặc bộ nhớ. Nhìn vào các giá trị hiện tại cho mpm_prefork_module hoặc mpm_worker_module và điều chỉnh cho phù hợp để đáp ứng nhu cầu của bạn.

Máy chủLimit 512
Tối đa 512

Chà, tôi có thực sự cần điều này với điều kiện là tôi có nginx trước apache2, vì vậy tôi tin rằng không có nhiều thứ để có nhiều hơn các lõi vật lý * 2 quy trình Apache2 ....
BarsMonster

Chỉ cần xác minh điều này. Việc tăng số lượng quy trình Apache2 từ 4 lên 16 không cải thiện hiệu năng chút nào (thậm chí nó đã giảm 0,5%). Tăng số lượng công nhân nginx lên 2 hoặc 4 không cải thiện được gì.
BarsMonster

1
Nếu dữ liệu của bạn khá tĩnh, tức là nó không cập nhật mọi tải trang khác, bạn có thể tăng query_cache của mình. MySQL sẽ giữ tập kết quả theo cách đó và lấy từ bộ nhớ. Tuy nhiên, nếu bảng đang được lưu trong bộ nhớ cache nhận được bất kỳ ghi nào trong thời gian đó, nó sẽ làm mất hiệu lực bộ đệm (ngay cả khi dữ liệu không bị ảnh hưởng), khiến nó bị lãng phí bộ nhớ.
Erik Giberti

Ngay bây giờ tôi thấy tỷ lệ truy cập bộ nhớ cache truy vấn 100% và MySQL vẫn cảm thấy chậm ...
BarsMonster

1
Thêm giải pháp bỏ qua tên vào tệp cấu hình MySQL của bạn. Điều đó sẽ lưu một tra cứu DNS trên mọi kết nối đến máy chủ. Hạn chế ở đây là tất cả các kết nối sẽ cần phải bị khóa bởi IP (giả sử bạn không sử dụng '%'). Nếu SQL ở trên cùng một máy chủ và không cần phải truy cập ở bất kỳ nơi nào khác ngoài localhost, bạn cũng có thể thêm mạng bỏ qua để loại bỏ toàn bộ ngăn xếp TCP / IP. Tuy nhiên, tôi nghĩ nút cổ chai là Apache.
Erik Giberti

0

Là tải này được tạo ra bởi một công cụ hoặc tải trong thế giới thực?

Bạn có thể muốn kiểm tra memcached. Tôi đã thấy các vấn đề ở tốc độ kết nối cao của nó gây ra độ trễ trong ứng dụng.

Nếu sử dụng trình tạo tải, bạn sẽ nhận được gì khi nhấn một trang tĩnh nhỏ?

Trong quá trình tải, bạn có thể muốn kiểm tra ngăn xếp mạng để biết các điều kiện TIME_WAIT. Có lẽ bạn đang lấp đầy hàng đợi kết nối của bạn.

Có thêm khoảng 100 lý do và vật phẩm bạn có thể xem nhưng không có thêm thông tin, tôi chỉ đưa ra dự đoán vào thời điểm này.


Nó đã được thử nghiệm thông qua ab-c 10 -t 10 URL Tôi đang đo điểm chuẩn từ chính máy chủ, vì vậy mạng không phải là vấn đề. Tôi đã đăng nhiều điểm chuẩn hơn theo yêu cầu của bạn.
BarsMonster

Tôi sẽ không dành quá nhiều nỗ lực điều chỉnh với ab. Bạn có thể thấy nó không chuyển thành hiệu suất trong thế giới thực. Những gì bạn có thể muốn làm là mổ xẻ ứng dụng của bạn và kiểm tra từng thành phần. Ví dụ, nhấn trực tiếp máy chủ apache chỉ bằng một trang tĩnh rất nhỏ. Điều này sẽ cung cấp cho bạn và ý tưởng về req / giây tối đa của bạn trên phần phụ trợ. Đặt nginx ở phía trước, kiểm tra lại gọi cùng một tệp phụ trợ. Sau đó thử nghiệm với một trang php kiểu "hello world" đơn giản Đôi khi tất cả các lớp có thể che giấu một cái gì đó đơn giản. Ngoài ra, xem các kết nối trong quá trình thử nghiệm. Hãy chắc chắn rằng ngăn xếp mạng của bạn không được lấp đầy.
jeffatrackaid

Tôi đã làm những điểm chuẩn này ngày hôm qua, và chúng nằm trong phần mô tả câu hỏi ban đầu được cập nhật. Ngoài ra, các bài kiểm tra được thực hiện trên localhost, vì vậy mạng không phải là vấn đề.
BarsMonster

Mạng có thể là một vấn đề ngay cả khi được thực hiện trên một máy chủ lưu trữ cục bộ. Không có khả năng trong trường hợp của bạn nhưng nó có thể gây ra vấn đề. Ít nhất bây giờ bạn có giới hạn trên ~ 450 req / giây với thiết lập PHP hiện tại của bạn. Bước tiếp theo là thả vào một cuộc gọi cơ sở dữ liệu và xem nó thay đổi như thế nào. Tôi thích phá vỡ điều này khi thực hiện điều chỉnh mức cao vì nó thực sự có thể giúp bạn xác định chính xác lớp gây ra nhiều vấn đề nhất.
jeffatrackaid

-1

99% các vấn đề thời gian như thế này sẽ truy ngược lại cơ sở dữ liệu. Hãy chắc chắn rằng các chỉ số đánh của bạn trước hết. Nếu điều đó không làm việc, hãy bắt đầu lưu trữ mọi thứ mà bạn có thể.


Đó là tất cả các chỉ mục và như tôi đã nói, nó thậm chí còn nhấn bộ đệm truy vấn MySQL trong 100% trường hợp
BarsMonster

-1

Tôi khuyên bạn nên sử dụng (nếu có thể) một nhóm kết nối để giữ cho cơ sở dữ liệu được kết nối với các ứng dụng web của bạn (không cần kết nối lại ở mỗi yêu cầu). Điều đó có thể tạo ra một sự khác biệt rất lớn về tốc độ.

Ngoài ra, hãy thử phân tích tất cả các truy vấn của bạn bằng EXPLAIN (và tại sao không cấu hình các truy vấn của bạn với SHOW PROFILE?).


Tất cả các truy vấn sử dụng chỉ mục. Nhóm kết nối MySQL được sử dụng.
BarsMonster
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.