【问题标题】:Azure Multi Container Web App stops the site apperently for no reasonAzure 多容器 Web 应用程序无故停止站点
【发布时间】:2021-07-05 13:34:36
【问题描述】:

我正在尝试在应用服务中设置带有 MySQL 容器的 Spring Boot API。这是我正在使用的 docker-compose 文件:

version: '3.8'
services:
  mysql:
    image: mysql:8
    container_name: mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=${__dc__MYSQL_ROOT_PASSWORD}
      - MYSQL_USER=${__dc__MYSQL_USERNAME}
      - MYSQL_PASSWORD=${__dc__MYSQL_PASSWORD}
      - MYSQL_DATABASE=${__dc__MYSQL_DATABASE}

  thesisapi:
    image: ${__dc__IMAGE}
    container_name: thesisapi
    restart: always
    ports:
      # Azure Web App exposes port 80
      - 80:${__dc__SERVER_PORT}
    depends_on:
      - mysql
    environment:
      - SERVER_PORT=${__dc__SERVER_PORT}
      - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/${__dc__MYSQL_DATABASE}
      - SPRING_DATASOURCE_USERNAME=${__dc__MYSQL_USERNAME}
      - SPRING_DATASOURCE_PASSWORD=${__dc__MYSQL_PASSWORD}
      - SPRING_DATASOURCE_DRIVER_CLASS_NAME=com.mysql.cj.jdbc.Driver
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - SPRING_JPA_DATABASE_PLATFORM=org.hibernate.dialect.MySQL5InnoDBDialect

注意 1 我在本地运行了上面的 docker-compose,它运行良好。

注意2上传文件到App Service时,有实际值而不是变量,即${foo}。

图片的下载工作正常。 MySQL 服务器启动并说它正在等待连接,但我的应用程序失败了几次,直到 MySQL 服务准备就绪。根据我在 ms 文档中看到的,depends_on 被忽略了。

在几次失败后,我的 API 启动,但由于某种原因,应用服务决定停止容器并重试。然后它又一次又一次地做同样的事情,以此类推……我已经尝试了几天来让它工作,这让我很紧张。

我还有一个前端应用图像,我正在上传到应用服务,但它不依赖于其他服务,并且可以启动并且可以使用。

我收集的日志:

INFO 1 --- [ task-1] o.hibernate.annotations.common.Version : HCANN000001: Hibernate Commons Annotations {5.1.0.Final}
INFO 1 --- [ task-1] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
ERROR 1 --- [ task-1] com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Exception during pool initialization.
com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

...

WARN 1 --- [ task-1] o.h.e.j.e.i.JdbcEnvironmentInitiator : HHH000342: Could not obtain connection to query metadata : Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

...

INFO 1 --- [         task-1] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL5InnoDBDialect
INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 5000 (http) with context path '/api'
INFO 1 --- [           main] DeferredRepositoryInitializationListener : Triggering deferred initialization of Spring Data repositories…
INFO 1 --- [         task-1] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
INFO 1 --- [         task-1] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'default'
INFO 1 --- [           main] DeferredRepositoryInitializationListener : Spring Data repositories initialized!
INFO 1 --- [           main] my.app.MyApplication                     : Started MyApplication in 25.648 seconds (JVM running for 28.112)
INFO  - Stopping site bsdeploydev3api because it failed during startup.

更新

所以我放弃了同时运行我的应用程序和 MySQL 容器,而是为 MySQL 创建了一个专用的 Azure 资源,称为 Azure Database for MySQL server。

一切设置完成后,我的应用仍然无法连接到数据库,这次的问题是:

java.sql.SQLException:服务器时区值“协调世界时”无法识别或代表多个时区。如果您想利用时区支持,您必须配置服务器或 JDBC 驱动程序(通过“serverTimezone”配置属性)以使用更具体的时区值。

为了解决这个问题,我必须在连接字符串中设置?serverTimezone=UTC。之后它就开始工作了。

现在我想知道以下几点:

  • 当我在本地运行上述 docker-file 时,我没有遇到这个问题。我想如果 MySQL 服务器和尝试连接它的应用程序位于同一系统上,则无需设置该查询参数。

  • 这是否也是部署到App Service 的容器的问题?实际上,它们生活在同一台机器上,我认为行为应该与本地相同。

所以,如果有人对此有见解,那就太好了。

【问题讨论】:

    标签: mysql spring azure docker azure-web-app-service


    【解决方案1】:

    不确定您是否仍在寻找答案,但我已通过以下方式在 api 中添加了entrypoint:

    entrypoint: ["./wait_for.sh", "db:3306", "-t", "3600", "--", "execute", "api"]

    这里./wait_for.sh取自https://github.com/vishnubob/wait-for-it

    db:3306是我的api所依赖的3306上运行的mysql数据库

    最后两个参数是执行我的api的命令行。

    以下是我的 docker-compose 文件。

    version: '3.8'
    
    services:
       db:
         image: mysql
         volumes:
           - mysql:/var/lib/mysql
         environment:
           - MYSQL_DATABASE=dbName
           - MYSQL_ROOT_PASSWORD=MyRootPassword!
           - MYSQL_USER=dbUser_1
           - MYSQL_PASSWORD=dbUser_1sPassword!
         restart: always
    
       api:
         depends_on:
           - db
         entrypoint: ["./wait_for.sh", "db:3306", "-t", "3600", "--", "execute", "api"] #waiting very long enough to set the db server up and running
         image: <my registry url>/api:latest
         ports:
           - "80:80"
         restart: always
    
    volumes:
      mysql:
            driver: azure_file
            driver_opts:
              share_name: Azure_Share_Name
              storage_account_name: Azure_Storage_Account_Name
              storageaccountkey: Azure_Key
    

    【讨论】:

    • 这看起来很酷。我想我会处理应用程序内部的等待,但是将来当我需要我无法处理的同步时,我肯定会使用它。感谢分享。
    【解决方案2】:

    我在问答环节responded 给您的question。在多容器应用程序上,要点是 depends_on isn't supported,它会被忽略。我建议删除对 MySQL 映像的启动依赖。

    【讨论】:

    • 如果您对我为该问题所做的最后更新有任何见解,这对任何在此问题上苦苦挣扎的人都会非常有用。
    • @Vivere 我认为不会,因为show variables like 'time_zone'; 的时区很可能会设置为 SYSTEM。我不是 100% 确定,但我认为 Azure MySQL 的来宾操作系统是 WIndows,而 base mysql 是基于 Debian。这可能就是您之前没有遇到问题的原因。
    猜你喜欢
    • 2021-04-19
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 2015-04-11
    • 1970-01-01
    • 2017-03-30
    • 1970-01-01
    相关资源
    最近更新 更多