hyperf / hyperf

🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.
https://www.hyperf.io
MIT License
6.19k stars 1.21k forks source link

[BUG] Redis just stoped working inside coroutines "PHP Fatal error: Uncaught RedisException: Operation timed" #7092

Closed volodymyr-hordiienko closed 1 week ago

volodymyr-hordiienko commented 1 week ago

Please answer these questions before submitting your issue.

  1. What did you do? If possible, provide a simple script for reproducing the error.
    
    redisConnect('Default');

\Swoole\Coroutine\run(function() { \Swoole\Coroutine::create(function () { redisConnect('Coroutine'); }); echo'End Coroutine. Waiting connect' . PHP_EOL; });

function redisConnect(string $prefix) { $s = ['redis', 6379, 5.0, NULL, 0, 0.0] ; echo $prefix . ' Connection Creating' . PHP_EOL; $redis = new Redis(); echo $redis->connect($s[0], $s[1], $s[2], $s[3], $s[4], $s[5]) ? 'Connected' : 'Not Connected'; echo PHP_EOL; }


2. What did you expect to see?
Connected in both cases

3. What did you see instead?

Default Connection Creating Connected Coroutine Connection Creating End Coroutine. Waiting connect PHP Fatal error: Uncaught RedisException: Operation timed out in /opt/www/test.php:17 Stack trace:

0 /opt/www/test.php(17): Redis->connect()

1 /opt/www/test.php(6): redisConnect()

2 [internal function]: {closure}()

3 {main}

thrown in /opt/www/test.php on line 17


But if I use deprecated Swoole\Coroutine\Redis()

\Swoole\Coroutine\run(function() { \Swoole\Coroutine::create(function () { redisConnect('Coroutine'); }); echo'End Coroutine. Waiting connect' . PHP_EOL; });

function redisConnect(string $prefix) { $s = ['redis', 6379, 5.0, NULL, 0, 0.0] ; echo $prefix . ' Connection Creating' . PHP_EOL; $redis = new Swoole\Coroutine\Redis(); echo $redis->connect($s[0], $s[1]) ? 'Connected' : 'Not Connected'; echo PHP_EOL; }


i get connection

Coroutine Connection Creating End Coroutine. Waiting connect Connected


4. What version of Swoole are you using (show your `php --ri swoole`)?

php --ri swoole

swoole

Swoole => enabled Author => Swoole Team team@swoole.com Version => 5.1.4 Built => Sep 5 2024 03:28:04 coroutine => enabled with boost asm context epoll => enabled eventfd => enabled signalfd => enabled spinlock => enabled rwlock => enabled openssl => OpenSSL 3.1.7 3 Sep 2024 dtls => enabled http2 => enabled json => enabled curl-native => enabled pcre => enabled c-ares => 1.27.0 zlib => 1.3.1 brotli => E16781312/D16781312 mutex_timedlock => enabled pthread_barrier => enabled async_redis => enabled coroutine_pgsql => enabled coroutine_odbc => enabled coroutine_sqlite => enabled

Directive => Local Value => Master Value swoole.enable_coroutine => On => On swoole.enable_library => On => On swoole.enable_fiber_mock => Off => Off swoole.enable_preemptive_scheduler => Off => Off swoole.display_errors => On => On swoole.use_shortname => Off => Off swoole.unixsock_buffer_size => 8388608 => 8388608


5. What is your machine environment used (show your `uname -a` & `php -v` & `gcc -v`) ?

uname -a Linux project.app 6.10.0-linuxkit #1 SMP PREEMPT_DYNAMIC Wed Jul 17 10:54:05 UTC 2024 x86_64 Linux

php -v PHP 8.3.8 (cli) (built: Jun 6 2024 17:04:22) (NTS) Copyright (c) The PHP Group Zend Engine v4.3.8, Copyright (c) Zend Technologies with Zend OPcache v8.3.8, Copyright (c), by Zend Technologies

gcc -v bash: gcc: command not found

{ "name": "hyperf/hyperf-skeleton", "type": "project", "keywords": [ "php", "swoole", "framework", "hyperf", "microservice", "middleware" ], "description": "A coroutine framework that focuses on hyperspeed and flexible, specifically use for build microservices and middlewares.", "license": "Apache-2.0", "require": { "php": ">=8.3", "ext-gd": "", "ext-openssl": "", "96qbhy/hyperf-auth": "^3.1", "doctrine/lexer": "^2.1", "fakerphp/faker": "^1.23", "friendsofhyperf/sentry": "^3.1", "hyperf/amqp": "^3.1", "hyperf/cache": "^3.1", "hyperf/command": "^3.1", "hyperf/config": "^3.1", "hyperf/crontab": "^3.1", "hyperf/database": "^3.1", "hyperf/database-pgsql": "^3.1", "hyperf/db-connection": "^3.1", "hyperf/engine": "^2.10", "hyperf/event": "^3.1", "hyperf/filesystem": "^3.1", "hyperf/framework": "^3.1", "hyperf/guzzle": "^3.1", "hyperf/http-server": "^3.1", "hyperf/logger": "^3.1", "hyperf/memory": "^3.1", "hyperf/process": "^3.1", "hyperf/redis": "^3.1", "hyperf/resource": "^3.1", "hyperf/translation": "^3.1", "hyperf/validation": "^3.1", "hyperf/view": "^3.1", "hyperf/view-engine": "^3.1", "kreait/firebase-php": "7.9.1", "yzen.dev/plain-to-class": "^3.0" }, "require-dev": { "hyperf/devtool": "^3.1", "hyperf/testing": "^3.1", "hyperf/watcher": "^3.1", "mockery/mockery": "^1.6", "slevomat/coding-standard": "^8.15", "squizlabs/php_codesniffer": "^3.10", "swoole/ide-helper": "^5.1", "symfony/var-dumper": "^v7.1", "zircote/swagger-php": "^4.10" }, "suggest": { "ext-json": "Required to use JSON.", "ext-pdo": "Required to use MySQL Client.", "ext-pdo_mysql": "Required to use MySQL Client.", "ext-redis": "Required to use Redis Client." }, "autoload": { "psr-4": { "App\": "app/" }, "files": [] }, "autoload-dev": { "psr-4": { "HyperfTest\": "./test/" } }, "minimum-stability": "dev", "prefer-stable": true, "config": { "optimize-autoloader": true, "sort-packages": true, "allow-plugins": { "php-http/discovery": true, "dealerdirect/phpcodesniffer-composer-installer": true } }, "extra": [], "scripts": { "post-root-package-install": [ "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" ], "post-autoload-dump": [ "rm -rf runtime/container" ], "cs-fix": "phpcbf --colors --standard=phpcs.xml ./app ./config", "cs-check": "phpcs --colors --standard=phpcs.xml ./app ./config", "test": ["php test/migrate.php && co-phpunit --prepend test/bootstrap.php -c phpunit.xml --colors=always"], "swagger": "php ./bin/hyperf.php swagger:gen -o ./storage/public/documentation/", "check-all": [ "@cs-fix", "@cs-check", "@test", "@swagger" ], "views-cache": "php ./bin/hyperf.php gen:view-engine-cache", "migrate": [ "Composer\Config::disableProcessTimeout", "php ./bin/hyperf.php migrate" ], "start": [ "Composer\Config::disableProcessTimeout", "php ./bin/hyperf.php start" ], "watch": [ "Composer\Config::disableProcessTimeout", "php ./bin/hyperf.php server:watch" ] } }


Its Dockerfile 

FROM hyperf/hyperf:8.3-alpine-v3.19-swoole-v5.1.4

COPY . /opt/www WORKDIR /opt/www

RUN cp /opt/www/entrypoint.sh.example /opt/www/entrypoint.sh

EXPOSE 80

ENTRYPOINT ["/opt/www/entrypoint.sh"]

but repeats with hyperf/hyperf:8.3-alpine-v3.19-swoole-v5.1.3 also

+

FROM redis:7.2.3

volodymyr-hordiienko commented 1 week ago

Ok, I found the issue, for anyone who is looking for, it was a problem with the fact that hyperf docker image based on alpine, alpine have issues with domain DNS resolve, as I used docker compose and connect to redis with service name host "redis", alpine does not connect me in that way, so the solution was to create custom network insede docker compose and assign static ip to redis service asn connec via IP

services:
  app:
    build: .
    container_name: "app.app"
    hostname: "app.app"
    restart: always
    env_file:
      - ./.env
    volumes:
      - .:/opt/www
    logging:
      driver: "json-file"
      options:
        max-size: "10M"
        max-file: "5"
    networks:
      cardinal_network:
        ipv4_address: 172.20.0.3

  nginx:
    build: .docker/nginx
    container_name: "app.nginx"
    hostname: "app.nginx"
    restart: always
    ports:
      - "443:443"
    depends_on:
      - app
    volumes:
      - ./.docker/nginx/nginx.conf:/etc/nginx/nginx.conf
      - ./storage/public:/opt/www/public
      - ./config/certificates:/opt/www/certificates
    logging:
      driver: "json-file"
      options:
        max-size: "10M"
        max-file: "5"
    networks:
      cardinal_network:
        ipv4_address: 172.20.0.2

  redis:
    container_name: "app.redis"
    hostname: "app.redis"
    build: .docker/redis
    restart: always
    environment:
      - ALLOW_EMPTY_PASSWORD=yes
    ports:
      - "6379:6379"
    volumes:
      - ./.docker/redis/data:/data
    logging:
      driver: "json-file"
      options:
        max-size: "10M"
        max-file: "5"
    networks:
      cardinal_network:
        ipv4_address: 172.20.0.4

networks:
  cardinal_network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16