Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JsSse in PHP-FPM setup requires special configuration #2178

Closed
mkrecek234 opened this issue Feb 26, 2024 · 5 comments · Fixed by #2187
Closed

JsSse in PHP-FPM setup requires special configuration #2178

mkrecek234 opened this issue Feb 26, 2024 · 5 comments · Fixed by #2187

Comments

@mkrecek234
Copy link
Contributor

mkrecek234 commented Feb 26, 2024

Situation:

  • You are using JsSse to send server-side updates to clients
  • You. are having an environment with Apache and PHP-FPM, buffering pages
  • The default in PHP-FPM under Apache is output buffering which destroys the possibility to use Sse, as the request will only be sent out to client if complete (or buffer size of typically 4096 is reached)

Solution:

  • Configure PHP-FPM in Apache module to allow flush by this configuration in php-fpm.conf for example:
    <FilesMatch ".+\.ph(?:ar|p|tml)$">
        SetHandler "proxy:unix:/run/php/php8.2-fpm.sock|fcgi://localhost"
    </FilesMatch>

    <Proxy "fcgi://localhost">
        ProxySet flushpackets=on
        ProxySet flushwait=20
        ProxySet max=10
        ProxySet timeout=100
    </Proxy>

Suggestions to limit flushing packets only on selected scripts or directories are welcome. This way you can keep output buffering for scripts that are non-Sse.

Also see:
php/php-src#12785 (comment)

@mkrecek234 mkrecek234 added the Clarity 🔍 Makes things easier to understand. label Feb 26, 2024
@mvorisek mvorisek removed the Clarity 🔍 Makes things easier to understand. label Feb 26, 2024
@mvorisek
Copy link
Member

mvorisek commented Feb 26, 2024

This seems to be not-output buffer related. Can anything from atk4/ui be done?

I tried to find some solutions and it seems sending at leasst 4096 bytes per each JSSE output can help, can you evaluate the possibilities?

https://gist.github.com/hranicka/368dfbf3df971f021fa70047eb894058

https://syntaxfix.com/question/45690/how-to-flush-output-after-each-echo-call

@mkrecek234
Copy link
Contributor Author

The PR in #2175 generally works. Only issue is that in FPM setup by default flush is not working (mod_fcgi) unless you activate it. Also you cannot reconfigure output buffer programmatically so you are stuck with an output buffer of 4096.

If you reconfigure PHP-FPM to allow flush as in above configuration, then Atk4 Ui works out of the box

@mvorisek
Copy link
Member

mvorisek commented Feb 26, 2024

then Atk4 Ui works out of the box

great

you are stuck with an output buffer of 4096.

we can account for that in SSE and always append 4kiB dummy string


working FMP/FCGI repro:

SetHandler "proxy:fcgi://127.0.0.1:9001/"
ProxyFCGISetEnvIf "true" SCRIPT_FILENAME "C:/.../atk4/ui/demos/interactive/sse.php"

<Proxy fcgi://127.0.0.1:9001/>
  ProxySet flushpackets=on
</Proxy>

and

php-cgi.exe -b 127.0.0.1:9001 -c "C:\...\Apache24\php\php.ini" -d display_errors=1
    -d display_startup_errors=1 -d error_reporting=E_ALL -d fastcgi.daemonize=0

@mvorisek mvorisek changed the title JsSse in PHP-FPM set-up requires special configuration JsSse in PHP-FPM setup requires special configuration Feb 27, 2024
@mvorisek
Copy link
Member

mvorisek commented Mar 25, 2024

I conducted a testing with various webservers:

Apache /w PHP FCGI is problematic as the response is bufferent by Apache and flush() called in php is completely ignored.

Based on https://stackoverflow.com/questions/30707792/how-to-disable-buffering-with-apache2-and-mod-proxy-fcgi#36298336 and testing, I found out that JsSse->output('x-flush: ' . str_repeat('x', 4_096) . "\n"); does reliably work as a flush() replacement.

However, when Apache is configured to compress the output (using SetOutputFilter DEFLATE) for any content-type, ie. also text/event-stream responses, then 4096 bytes are not enough to enforce the output to be flushed. Based on testing, something between bin2hex(random_bytes(32 * 1024)) and bin2hex(random_bytes(64 * 1024)) was needed, ie. about 50 KB of incompressible overhead.

The question is, is it worth adding 4KiB of overheader to cover Apache /w PHP FCGI (and even only when configured to not compress all files)?

Apache issue: https://bz.apache.org/bugzilla/show_bug.cgi?id=68827

@mkrecek234
Copy link
Contributor Author

@mvorisek Can confirm that with fix #2187 we no longer have to adjust flushing in PHP-FPM to make JsSse work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants