webdevqa.jp.net

SpringBootアプリケーションにajpを使用するApacheの背後にあるTomcat

組み込みTomcatを使用するSpringBootアプリを使用してApacheWebサーバーを構成しようとしています。 Spring Bootの前は、次のようなajp.confファイルを作成していました。

<VirtualHost *:80>
   ServerName localhost
   <Proxy *>
      AddDefaultCharset Off
      Order deny,allow
      Allow from all
   </Proxy>

   ProxyPass /app ajp://localhost:8009/app
   ProxyPassReverse /app ajp://localhost:8009/app

 </VirtualHost>

そして、次のようにhttpd.confファイルに含めます

Include /opt/lampp/Apache2/conf/ajp.conf

また、Tomcatのserver.xmlファイルでは、ポート8009をリッスンするように構成していました。

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" connectionTimeout="5000"

この設定は機能します。しかし、今Spring Bootを使用して、組み込みTomcatで同様のことを達成しようとしています。 Spring Boot Documentation をここで読み、application.ymlファイルに次のプロパティを追加しました。

server:
    port: 8080
    Tomcat:
        remote_ip_header: x-forwarded-for
        protocol_header: x-forwarded-proto

私のajp.confファイルは次のようになります。

<VirtualHost *:80>
   ServerName localhost
   <Proxy *>
      AddDefaultCharset Off
      Order deny,allow
      Allow from all
   </Proxy>

   ProxyPass /app ajp://localhost:8009/
   ProxyPassReverse /app ajp://localhost:8009/

 </VirtualHost>

SpringBootのTomcat構成クラスを次のように使用しています

@Configuration
public class TomcatConfiguration {

private final Logger log = LoggerFactory.getLogger(TomcatConfiguration.class);

@Bean
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory Tomcat = new TomcatEmbeddedServletContainerFactory();
    Tomcat.addAdditionalTomcatConnectors(createConnector());
    Tomcat.addContextValves(createRemoteIpValves());
    return Tomcat;
}

private RemoteIpValve createRemoteIpValves(){
    RemoteIpValve remoteIpValve = new RemoteIpValve();
    remoteIpValve.setRemoteIpHeader("x-forwarded-for");
    remoteIpValve.setProtocolHeader("x-forwarded-protocol");
    return remoteIpValve;
}

private Connector createConnector() {
    Connector connector = new Connector("org.Apache.coyote.http11.Http11NioProtocol");
    Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
    connector.setScheme("ajp");
    connector.setProtocol("AJP/1.3");
    connector.setRedirectPort(8443);
    //connector.setSecure(true);
    connector.setPort(8009);
    return connector;
}

Apacheエラーログに次のように表示されます。

AH01080: ajp_msg_check_header() got bad signature 4854
[proxy_ajp:error] [pid 24073] AH01031: ajp_ilink_receive() received bad header
[proxy_ajp:error] ajp_read_header: ajp_ilink_receive failed
[proxy_ajp:error] (120007)APR does not understand this error code: [client xx.xx.xx.xx:60916] AH00878: read response failed from (null) (*)

ここで何が起こっているのかわからない。私はオンラインでたくさん検索しましたが、SpringBootアプリでApacheの背後にあるTomcatを提供する方法に関する適切なドキュメントを見つけることができませんでした。最終的には、複数のTomcatインスタンスも負荷分散したいと思います。

10
Nayan

上記のコメントから推測:

@Configuration
public class TomcatAjpConfig {

@Bean
@SuppressWarnings("static-method")
public EmbeddedServletContainerFactory servletContainer() {
    TomcatEmbeddedServletContainerFactory Tomcat = new TomcatEmbeddedServletContainerFactory();
    Tomcat.addAdditionalTomcatConnectors(createConnector());
    Tomcat.addContextValves(createRemoteIpValves());
    return Tomcat;
}

private static RemoteIpValve createRemoteIpValves() {
    RemoteIpValve remoteIpValve = new RemoteIpValve();
    remoteIpValve.setRemoteIpHeader("x-forwarded-for");
    remoteIpValve.setProtocolHeader("x-forwarded-proto");
    return remoteIpValve;
}

private static Connector createConnector() {
    Connector connector = new Connector("AJP/1.3");
    connector.setPort(8009);
    return connector;
}

}
6
Tim

同様の問題がありましたが、HTTPプロキシに問題がありました。 Spring Boot 1.3をデバッグした後、次の解決策を見つけました。 AJPプロキシについても同様である必要があります。

1。Apacheプロキシでヘッダーを設定する必要があります。

<VirtualHost *:443>
    ServerName www.myapp.org
    ProxyPass / http://127.0.0.1:8080/
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Forwarded-Port 443
    ProxyPreserveHost On
    ... (SSL directives omitted for readability)
</VirtualHost>

2。これらのヘッダーを使用するようにSpringBootアプリに指示する必要があります。したがって、application.properties(またはSpring Bootsがプロパティを理解するその他の場所)に次の行を配置します。

server.use-forward-headers=true

これら2つのことを正しく行うと、アプリケーションが送信するすべてのリダイレクトはnotに移動します http://127.0.0.1:8080/ [パス] ただし自動的に https://www.myapp.com/ [path]

更新1。このトピックに関するドキュメントは ここ です。少なくともプロパティを知っておくためにそれを読む必要がありますserver.Tomcat.internal-proxiesこれは信頼できるプロキシサーバーのIPアドレスの範囲を定義します。

3
Igor Mukhin

構成可能なthroughtプロパティまたはymlファイル。

@Configuration
@ConfigurationProperties(prefix = "Tomcat")
public class TomcatConfiguration {
   private int ajpPort = 8009;

   private boolean ajpAllowTrace = false;
   private boolean ajpSecure = false;
   private String ajpScheme = "http";
   private boolean ajpEnabled;


  @Bean
  public EmbeddedServletContainerFactory servletContainer() {

    TomcatEmbeddedServletContainerFactory Tomcat = new TomcatEmbeddedServletContainerFactory();
    if (isAjpEnabled()) {
        Connector ajpConnector = new Connector("AJP/1.3");
        ajpConnector.setProtocol("AJP/1.3");
        ajpConnector.setPort(getAjpPort());
        ajpConnector.setSecure(isAjpSecure());
        ajpConnector.setAllowTrace(isAjpAllowTrace());
        ajpConnector.setScheme(getAjpScheme());
        Tomcat.addAdditionalTomcatConnectors(ajpConnector);
    }

    return Tomcat;
    }
// ... Get/Set
}

application.yml

Tomcat:
  ajpEnabled: true
  ajpPort: 9009
  ...
1
pdorgambide