1

application_name是一个 PostgreSQL 特定的连接参数,每个客户端在连接时可以(并且应该)设置它。它稍后会帮助 DBA 和操作人员将行为不端的查询与特定的应用程序代码相关联。

这个 SO question 解释了如何application_name使用 SQLAlchemy进行设置,但不幸的是,它在 Heroku 上不起作用,因为设置application_name是在 PostgreSQL8.5分支上添加的(仅发布为),而安装在 Heroku 测功机上9.0的 PostgreSQL 客户端库( )版本是libpq从 PostgreSQL 8.4.9 构建。

如果有的话,可以做些什么来设置application_nameHeroku?

4

1 回答 1

1

据我所知,唯一的解决方案是向您的 slug提供更新版本的服务。libpq

我的目标包是libpq5libpq-dev,它们是从源包postgresql-9.1构建的。为了节省大量工作,并且如果您信任我的二进制文件,您可以直接跳到第 8 步并使用我制作的预构建二进制 libpq。不不,不要感谢我。

  1. 使用 vanilla 12.04 启动新 VM
  2. sudo apt-get update
  3. apt-get source postgresql-9.1(你可能需要sudo apt-get install dpkg-src先)
  4. 在提取的源代码中,查看规则文件(postgresql-9.1-9.1.8/debian/rules如果precise-updates仍在 PostgreSQL 9.1.8 中)。
  5. 从规则文件中,我相信我们应该用于构建 libpq 的配置选项是:

    LDFLAGS="-Wl,--as-needed -Wl,-z,now" \
    CFLAGS="-fPIC -DLINUX_OOM_ADJ=0" \
    ./configure --prefix=/app/vendor \
      --enable-integer-datetimes \
      --enable-thread-safety \
      --enable-debug \
      --disable-rpath \
      --with-gnu-ld \
      --with-pgport=5432 \
      --with-system-tzdata=/usr/share/zoneinfo \
      --without-tcl \
      --without-perl \
      --without-python \
      --with-krb5 \
      --with-gssapi \
      --with-openssl \
      --with-libxml \
      --with-libxslt \
      --with-ldap
    

    请注意,我删除/否定--enable-nls --with-ossp-uuid --with-tcl --with-perl --without-python --with-pam了,因为在 Heroku dyno 上它们会导致配置/构建失败。我不需要它们中的任何一个,我不确定它们是否会产生影响libpq5,我怀疑它们在测功机上非常需要,如果您觉得不一样,请享受修复它的乐趣,我向您致敬,好先生。

  6. make && make install

  7. 现在所有的 postgresql 都安装到/vendor. 我们需要获取的文件在postgresql-9.1-9.1.8/debian/libpq5.install和中指定postgresql-9.1-9.1.8/debian/libpq-dev.install。唉,因为我们没有遵循 debian 的安装布局,我们需要调整这些列表来找到我们真正需要的文件。我想出了这个清单:

    tar c \
        include/postgresql/internal/* \
        include/libpq-fe.h \
        include/libpq-events.h \
        include/libpq/libpq-fs.h \
        include/pg_config*.h \
        include/postgres_ext.h \
        include/postgresql/9.1/server/catalog/pg_type.h \
        include/postgresql/9.1/server/catalog/genbki.h \
        include/postgresql/9.1/server/nodes/nodes.h \
        include/postgresql/9.1/server/utils/elog.h \
        include/postgresql/9.1/server/utils/errcodes.h \
        include/postgresql/9.1/server/utils/palloc.h \
        include/postgresql/9.1/server/c.h \
        include/postgresql/9.1/server/pg_config.h \
        include/postgresql/9.1/server/pg_config_manual.h \
        include/postgresql/9.1/server/pg_config_os.h \
        include/postgresql/9.1/server/port.h \
        include/postgresql/9.1/server/pg_trace.h \
        include/postgresql/9.1/server/postgres.h \
        include/postgresql/9.1/server/postgres_fe.h \
        include/postgresql/9.1/server/postgres_ext.h \
        include/postgresql/9.1/server/mb/pg_wchar.h \
        lib/libpq.so \
        bin/pg_config \
        lib/libpq.so.5* \
        | gzip --best > /tmp/libpq-5.4_9.1.8.tar.gz
    

    请注意,我必须删除联机帮助页 ( pg_config.1.gz) 和本地化消息 ( LC_MESSAGES/pg_config-9.1.mo LC_MESSAGES/libpq*.mounder share/locale),由于某种原因,它们不是基于我的测功机构建的。我设法将 Python 链接到psycopg2这个文件列表并成功使用它,但如果你觉得它很重要,你也可以弄清楚并修复它。

  8. 我们的麻烦现在几乎结束了。您应该获取生成的libpq-5.4_9.1.8.tar.gz文件并将其放在您的 dyno 的 buildpack 可以访问的某个位置(如 S3),然后将其出售到 slug 中。如果您不确定如何执行此操作,我的建议(对于当前的Python buildpack)是您在 slug 中创建文件“bin/pre_compile”,并将其放入其中:

    #!/bin/sh
    
    vendor() {
        printf "       "
        echo -n "$1 "
        curl --location --fail --silent $1 | tar -zx -C vendor && echo OK
    }
    
    echo "       (lines by the app will be prefixed with ---->>)"
    
    echo "---->> Fetching vendored binaries"
    mkdir -p vendor
    vendor "http://fusic.s3.amazonaws.com/executables/heroku/libpq-5.4_9.1.8.tar.gz"
    
    echo "---->> Injecting shell environment"
    # Even though Heroku's Python buildback has a hook mechanism, hooks can't
    #  change the buildpack's process environment (they are spawned, not
    #  sourced). This makes it possible to write hooks in any language, but
    #  makes vendoring stuff that should be linked against libraries installed
    #  during the rest of the build process harder. The kludge below hijacks
    #  $BIN_DIR/steps/pylibmc, which is sourced after this code and before pip
    #  is ran. Puked a little in my mouth.
    # See also: https://twitter.com/aknin/status/290832546260979712
    cat > $BIN_DIR/steps/pylibmc << EOF
    echo "---->> Injected environment hook executing"
    source .profile.d/activate_vendor_tree.sh
    EOF
    

    并创建.profile.d/activate_vendor_tree.sh并将其放入其中:

    #!sh
    
    export PATH="/app/vendor/bin:$PATH"
    export CFLAGS="-I/app/vendor/include"
    export LDFLAGS="-L/app/vendor/lib -R/app/vendor/lib"
    export LD_LIBRARY_PATH="/app/vendor/lib:$LD_LIBRARY_PATH"
    

    When compiling your slug, the pre-hook we installed kicks in, downloads our backported libpq and vendors it into the slug. If you're using the Python buildpack or a similarly limited buildpack (see detailed comment above), the ugly but necessary environment injection hook kicks in, and your requirements will be compiled against the new libpq. When you run your app, Heroku conveniently source everything in .profile.d before executing your code, again activating the new libpq. Oh yeah.

  9. At long last, you're done. Deploy your app to Heroku, and your dependencies should link against the new libpq. If your app was already deployed, you'll probably need to clear your slug's cache dir before Heroku's slug compiler will try to reinstall these requirements (so they can be linked to your new libpq; this is a thorny topic, which is outside the scope of this tutorial; the only method I know is to stick something in the pre_compile that will delete the cache). Ugh.

于 2013-03-31T03:18:06.743 回答