2014-11-21 164 views
10

我一直在嘗試使用使用嵌入式Tomcat的Spring Boot應用程序來配置Apache Web服務器。春天啓動之前我用來創建像ajp.conf文件:Apache使用ajp用於Spring Boot應用程序的Tomcat

<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> 

,包括像

Include /opt/lampp/apache2/conf/ajp.conf 

httpd.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> 

我有我的春天啓動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) (*) 

不確定這裏發生了什麼事。我在網上搜索了很多,但找不到一篇關於如何在Spring後面的apache上使用tomcat的好文檔。最後,我想要負載平衡多個tomcat實例。

+1

http://docs.spring.io/autorepo/docs/spring-boot/1.0.0.RC4/api/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.html#setProtocol %28java.lang.String%29或http://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html#howto-enable-multiple-connectors-in -tomcat。 – 2014-11-21 22:44:16

+2

你爲什麼要創建HTTP NIO連接器?您需要創建AJP連接器 - 「新連接器(」AJP/1.3「)'。 – 2014-11-22 16:11:49

+1

@PavelHoral你把我推向了正確的方向。當我使用org.apache.coyote.ajp.AjpProtocol連接器時,它工作。不知道,我如何做是最好的辦法。但是,它現在起作用了。萬分感謝! – Nayan 2014-11-22 22:50:18

回答

6

從上述評論地推導出:

@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; 
} 

} 
3

也有類似的問題,但與HTTP代理。經過Spring Boot 1.3的一些調試後,我發現了以下解決方案。它應該與AJP代理類似。

你不得不安裝在頭部上的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.你必須告訴你的Spring應用程序啓動使用這些頭。所以,把你的application.properties以下行(或在春天靴子理解性質的任何其它地方):

server.use-forward-headers=true 

如果你正確地做這兩件事情,每一個重定向您的應用程序發送將http://127.0.0.1:8080/[path]但自動爲https://www.myapp.com/[path]

更新1.有關該主題的文檔是here。您應該至少閱讀它以瞭解屬性server.tomcat.internal-proxies,它定義了可以信任的代理服務器的IP地址範圍。

+0

不錯的加法;這也是我所想到的。所有的偉大工程,具有小問題,當我用彈簧HATEOAS'ControllerLinkBuilder.linkTo' +'methodOn'我生成的鏈接以https開頭,也包含端口號443。當我用'BasicLinkBuilder'端口沒有加入網址。對此有何想法? – Tim 2016-01-07 14:32:40

+0

@tim從未與這些類一起工作。您可以嘗試調試到ContollerLinkBuilder和BasicLinkBuilder中。如果他們有區別,你可以發佈一個bug報告給Spring的人。他們反應非常快。 – 2016-01-08 20:06:46

0

可配置的屬性或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 
} 

申請。陽明海運

tomcat: 
    ajpEnabled: true 
    ajpPort: 9009 
    ... 
相關問題