Apache + SpringBoot 연동

2023. 10. 19. 15:45plming/Java-Spring Boot

  • Port : http(80) → https(443) → ajp(9010) SpringBoot로 연결
    • ajp Port는 임의로 정한 것임.
  • OS : ubuntu

 

  • Apache 설치
sudo apt-get update
sudo apt-get install apache2
  •  
  • 80 port로 요청이 들어오면
  • 443 port로 전달하도록 설정
sudo vi /etc/apache2/sites-available/000-default.conf
<VirtualHost *:80>
	...
    RewriteEngine on
    RewriteCond %{SERVER_NAME} = aaa.bbb.ccc
    RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>

 

 

  • mod-jk 설치 (Apache와 SpringBoot(embedded tomcat)연동 모듈)
sudo apt-get install libapache2-mod-jk

 

 

  • application.properties 에 ajp 설정 추가
tomcat.ajp.protocol = AJP/1.3
tomcat.ajp.port = 9010
tomcat.ajp.enabled = true

     - 9010 Port는 임의로 정한 것임

 

  • ajp 연결Bean 추가
@Configuration
public class AjpConfig {

  @Value("${tomcat.ajp.port}")
  int ajpPort;

  @Value("${tomcat.ajp.enabled}")
  boolean ajpEnabled;

  @Value("${tomcat.ajp.protocol}")
  String ajpProtocol;

  @Bean
  public TomcatServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    if( ajpEnabled ) {
      Connector ajpConnector = new Connector( ajpProtocol );
      ajpConnector.setPort( ajpPort );
      ajpConnector.setSecure( false );
      ajpConnector.setScheme( "https" );  // or http
      ajpConnector.setAllowTrace( false );

      ((AbstractAjpProtocol)ajpConnector.getProtocolHandler()).setSecretRequired( false );

      tomcat.addAdditionalTomcatConnectors( ajpConnector );
    }
    return tomcat;
  }

}

     -  https를 사용하는 경우이므로

        setScheme( "https" ); 를 사용함.

 

     -  아래 Exception이 발생하며, SpringBoot가 실행되지 않는다면

        setSecretRequired( false ); 코드가 있어야 한다.

|ERROR|org.apache.catalina.LifecycleException: Protocol handler start failed
	at org.apache.catalina.connector.Connector.startInternal(Connector.java:1067)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.StandardService.addConnector(StandardService.java:227)
	at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.addPreviouslyRemovedConnectors(TomcatWebServer.java:282)
Caused by: java.lang.IllegalArgumentException: The AJP Connector is configured with secretRequired="true" but the secret attribute is either null or "". This combination is not valid.
	at org.apache.coyote.ajp.AbstractAjpProtocol.start(AbstractAjpProtocol.java:270)
	at org.apache.catalina.connector.Connector.startInternal(Connector.java:1064)
	at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
	at org.apache.catalina.core.StandardService.addConnector(StandardService.java:227)
org.apache.juli.logging.DirectJDKLog.log (175) | main  :: Failed to start component [Connector[AJP/1.3-9010]]

|WARN |org.springframework.context.support.AbstractApplicationContext.refresh (559) | main  :: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Failed to start bean 'webServerStartStop'; nested exception is org.springframework.boot.web.embedded.tomcat.ConnectorStartFailedException: Connector configured to listen on port 9010 failed to start

 

     -  ajp관련 Exception도 나지 않고

        SpringBoot도 잘 실행되었는데...

        ajp port관련 Log가 나타나지 않는다면?

        연동될 때는 나타날 수 있으니, ㄱㄱ

INFO 12972 --- [           main] org.apache.coyote.ajp.AjpNioProtocol     : Initializing ProtocolHandler ["ajp-nio-9010"]
INFO 12972 --- [           main] org.apache.coyote.ajp.AjpNioProtocol     : Starting ProtocolHandler ["ajp-nio-9010"]
INFO 12972 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 9010 (http)

 

 

  • ajp.port를 처리할 worker 설정파일 생성
sudo vi /etc/apache2/workers.properties
worker.list=ajp13_worker

worker.ajp13_worker.port=9010
worker.ajp13_worker.host=localhost
worker.ajp13_worker.type=ajp13
worker.ajp13_worker.lbfactor=1

worker.loadbalancer.type=lb
worker.loadbalancer.balance_workers=ajp13_worker

 

  • 위에서 만든 worker 설정파일이 사용되도록 변경
sudo vi /etc/apache2/mods-available/jk.conf

        #기존 설정을 주석처리

#JkWorkersFile /etc/libapache2-mod-jk/workers.properties
JkWorkersFile /etc/apache2/workers.properties

 

 

  • Apache 443 Port처리 시
  • 위에서 설정한 worker 로 처리되도록 Apache SSL설정에 추가
sudo vi /etc/apache2/sites-available/000-default-le-ssl.conf
<IfModule mod_ssl.c>
  <VirtualHost *:443>
    :::
    JkMount /* ajp13_worker
  </VirtualHost>
</IfModule>

     -  80 Port만 사용하는 경우

        000-default.conf 에 추가하면 됨.

 

 

  • Apache 재시작
sudo service apache2 restart

 

     -  ajp worker가 잘 연결되었는지 LOG파일 확인

        ajp worker로 지정한 이름이 error 에 표시되면

        - workers.properties 파일의 worker.list에 이름이 있는지

        - 000-default-le-ssl.conf 파일의 JkMount부분에 이름이 있는지

        확인해보자.

tail -f /var/log/apache2/mod_jk.log
[info] init_jk::mod_jk.c (3591): mod_jk/1.2.48 initialized
[error] extension_fix::jk_uri_worker_map.c (579): Could not find worker with name 'jk-manager' in uri map post processing.
[error] extension_fix::jk_uri_worker_map.c (579): Could not find worker with name 'jk-status' in uri map post processing.
[error] extension_fix::jk_uri_worker_map.c (579): Could not find worker with name 'ajp13_worker' in uri map post processing.
[error] jk_handler::mod_jk.c (2999): Could not find a worker for worker name=ajp13_worker

     -  jk-manager, jk-status는 필요시에 처리하면 됨.

        이번 mission에서는 PASS

 

 

  • SpringBoot 실행
  • 지정한 페이지 접근되는지 확인

     -  Apache Log 확인

tail -f /var/log/apache2/booking-access.log

 

     -  SpringBoot Log에서 ajp Log 확인

|DEBUG|com...... (90) | ajp-nio-127.0.0.1-9010-exec-3  :: ...