교착 상태에 빠지지 않게 하기 위해 비관점 잠금 타임아웃을 설정할 수 있다. 

Map<String, Object> hints = new HashMap<>();
hints.put("javax.persistence.lock.timeout", 2000);
Order order = entityManager.find(Order.class, LockModeType.PESSIMISTIC_WRITE, hints);

 

@Lock(LockModeType.PESSIMISTIC_WRITE)
@QueryHints({
	@QueryHint(name="javax.persistence.lock.timeout", value="2000" )
})
@Query("select m from Member where m.id = :id")
Optional<Member> findByIdForUpdate(@Param("id") MemberId memberId);

자바 설치 

sudo amazon-linux-extras enable corretto8
sudo yum clean metadata
sudo yum install java-1.8.0-amazon-corretto-devel

자바의 설치 경로를 확인합니다. 

$ which java
/usr/bin/java

$ readlink -f /usr/bin/java
/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64/jre/bin/java

자바를 환경설정 JAVA_HOME 설정

sudo vi /etc/profile

export JAVA_HOME=/usr/lib/jvm/java-1.8.0-amazon-corretto.x86_64
export PATH=$PATH:$JAVA_HOME/bin
export CLASSPATH=$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tools.jar

source /etc/profile

HBase 설치

wget http://archive.apache.org/dist/hbase/1.2.7/hbase-1.2.7-bin.tar.gz
tar -zxvf hbase-1.2.7-bin.tar.gz
rm hbase-1.2.7-bin.tar.gz

hbase-1.2.7/conf/hbase-env.sh 파일 수정

# Configure PermSize. Only needed in JDK7. You can safely remove it for JDK8+
export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"
export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"

위 두줄을 주석 처리하여 준다. 

hbase-1.2.7/conf/hbase-site.xml 파일 수정

 <configuration>
      <property>
          <name>hbase.rootdir</name>
          <value>file:///home/ec2-user/pinpoint/data</value>
      </property>
      <property>
          <name>hbase.zookeeper.property.dataDir</name>
          <value>/home/ec2-user/pinpoint/zookeeper</value>
      </property>
  </configuration>

실행

hbase-1.2.7/bin/start-hbase.sh

hbase 스키마 생성

cd /home/ec2-user/pinpoint/hbase-1.2.7/bin
wget https://raw.githubusercontent.com/pinpoint-apm/pinpoint/master/hbase/scripts/hbase-create.hbase

TTL 값이 31536000 초(365일), 5184000 초(60 일)로 데이터를 유지하도록 되어있어 604800 초(7일)로 변경

sed 's/31536000/604800/' hbase-create.hbase > hbase-create-real.hbase
sed -i 's/5184000/604800/' hbase-create-real.hbase

스키마 생성

./hbase shell ./hbase-create-real.hbase

Pinpoint Collector 설치 및 실행

wget https://github.com/pinpoint-apm/pinpoint/releases/download/v2.2.0/pinpoint-collector-boot-2.2.0.jar
nohup java -jar -Dpinpoint.zookeeper.address=localhost pinpoint-collector-boot-2.2.0.jar 1>/dev/null 2>&1 &

Pinpoint Web 설치 및 실행

wget https://github.com/pinpoint-apm/pinpoint/releases/download/v2.2.0/pinpoint-web-boot-2.2.0.jar
nohup java -jar -Dpinpoint.zookeeper.address=localhost pinpoint-web-boot-2.2.0.jar 1>/dev/null 2>&1 &

 

Pinpoint Agent 설치

wget https://github.com/pinpoint-apm/pinpoint/releases/download/v2.2.0/pinpoint-agent-2.2.0.tar.gz
tar -zxvf pinpoint-agent-2.2.0.tar.gz

vi /pinpoint-agent-2.2.0/pinpoint-root.config 수정 

profiler.transport.grpc.collector.ip=192.168.0.207

 

아마존 영역에서 elasticsearch를 사용하기 위해서는 opensearch를 사용해야되는데 기존 elasticsearch 와 연동하는 부분이 라이센스 문제 때문에 삽질을 계속했다.  

logstash에서 opensearch로 데이터를 전송하기 위해서는 logstash-oss 다운받아야 하며 opensearch 모듈이 포함되어 있는 것을 다운 받아야 한다. (https://opensearch.org/downloads.html)

curl https://artifacts.opensearch.org/logstash/logstash-oss-with-opensearch-output-plugin-7.16.2-linux-x64.tar.gz -o logstash-oss-with-opensearch-output-plugin-7.16.2-linux-x64.tar.gz

tar -zxvf logstash-oss-with-opensearch-output-plugin-7.16.2-linux-x64.tar.gz

로그스태시 생성

/home/ec2-user/logstash-7.16.2/config/logstash.conf 파일 생성

input {
  file {
    path => ["/log/*.log"]
    start_position => "beginning"
  }
}
filter {
    json {
      source => "message"
      remove_field => ["message", "@timestamp", "@version"]
    }
}
output {
     opensearch {
        hosts       => ["https://:443"]
        user        => "user"
        password    => "password"
        index       => "logstash-logs"
    }
}

로그스태시  실행 

/home/ec2-user/logstash-7.16.2/bin/logstash -f /home/ec2-user/logstash-7.16.2/config/test.conf

토픽 생성

bin/kafka-topics.sh --create \
--bootstrap-server 카프카서버:9092 \
--replication-factor 1 \
--partitions 3 \
--topic 토픽이름

토픽 삭제

bin/kafka-topics.sh --delete --bootstrap-server 카프카서버:2181 --topic 토픽이름

토픽 리스트

bin/kafka-topics.sh  --bootstrap-server 카프카서버:9092 --list

토픽 상세

bin/kafka-topics.sh --bootstrap-server 카프카서버:9092 --describe --topic 토픽이름

컨슈머

컨슈머 확인

bin/kafka-console-consumer.sh --bootstrap-server 카프카서버:9092 --topic 토픽이름 --from-beginning

컨슈머 그룹 리스트

bin/kafka-consumer-groups.sh --bootstrap-server 카프카서버:9092 --list

컨슈머 그룹 상세

bin/kafka-consumer-groups.sh --bootstrap-server 카프카서버:9092 --describe --group 컨슈머그룹이름

 

조금이라도 정적인 자원들에 대해서 빨리 로딩하는 방법이 없을까 고민하고 있었는데  우연히 정적 리소스에 대한 cache와 compress를 보았다. 그래서 한 번 테스트 해볼까 한다. 

Cache 

application.json 에 아래 내용을 추가한다. (초단위 60x60x10 = 10시간) -> 테스트시간임

spring.resources.cache.period=36000

처음 호출 

처음 호출했을 경우 200과 함께 사이즈 시간을 볼 수있다. 

새로고침 을 누르고 다시 조회 보면 304 와 함께 max-age를 통해 캐쉬가 됨을 확인

사이즈와 시간이 줄어듬을 확인

처음 호출 이후에 지정된 시간까지 캐쉬를 통해 절약할 수 있음 알았다. 

자바소스에서는 WebMvcConfigurer 를 implements 하여 쓸 수 있다. 

registry.addResourceHandler("/**")
                .addResourceLocations("classpath:/static/")
                .setCachePeriod(36000)
        ;

Compress

압축을 해보자 . application.json 에 다음을 추가하자

server.compression.enabled=true
server.compression.mime-types=text/html,text/xml,text/plain,text/css,text/javascript,application/javascript
server.compression.min-response-size=2048

그리고 호출 

압축 안함
압축 이후에 시간 사이즈와 시간 비교이다 
gzip으로 압축됨을 표시

네트워크 환경에 따라서 속도는 다르게 나올 수 있다 하지만 사이즈가 엄청 크거나 로딩이 느리다면

고민해서 활용을 해보면 좋을 것 같다

@Bean 
UiConfiguration uiConfig() { 
	return UiConfigurationBuilder.builder() 
    .docExpansion(DocExpansion.LIST) // or DocExpansion.NONE or DocExpansion.FULL 
    .build(); 
}

source : http://springfox.github.io/springfox/docs/current/#springfox-swagger2-with-spring-mvc-and-spring-boot

 

Springfox Reference Documentation

The Springfox suite of java libraries are all about automating the generation of machine and human readable specifications for JSON APIs written using the spring family of projects. Springfox works by examining an application, once, at runtime to infer API

springfox.github.io

swagger (2.6.1)버전이 다른 경우 

@Bean
public UiConfiguration uiConfig() {
	return new UiConfiguration(
                null,
                "list",
                "alpha",
                "schema",
                UiConfiguration.Constants.DEFAULT_SUBMIT_METHODS,
                false,
                true,
                null
        );
}

 

서비스에 어노테이션으로 aop를 조정할 수 있다. 만약 서비스에서 로그인 관련 체크를 한다면 어노테이션을 선언하고 메서드에 어노테이션을 선언하는 것 만으로 aop 를 적용할 수 있다.

1. 인터페이스 선언 

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SecurityCheck {
}

타겟을 메서드에 준다

2. 체크할 포인트를 선언 

@Aspect
@Component
public class SecurityChecker {

  private static final Logger logger = LoggerFactory.getLogger(SecurityChecker.class);

  @Pointcut("@annotation(SecurityCheck)")
  public void checkMethodSecurity() {}

  @Around("checkMethodSecurity()")
  public Object checkSecurity (ProceedingJoinPoint joinPoint) throws Throwable {
    logger.debug("Checking method security...");
    // TODO Implement security check logics here
    Object result = joinPoint.proceed();
    return result;
  }
}

TODO 부분에 실제로 체크해야할 내용을 삽입한다.

3. 서비스 메서드에 적용 

  @SecurityCheck
  @Transactional(noRollbackFor = { UnsupportedOperationException.class })
  public Message save(String text)
  1. HttpServletRequest.getUserPrincipal() 으로 현재 사용자 정보를 가져올 수 있다.  
  2. SecurityContextHolder로 SecurityContextHolder.getContext().getAuthentication() 
  3. 스프링 시큐리트의 @AuthenticationPrincipal이 적용된 어노테이션을 생성할 있다. 그리고 스프링에 UserDetails 구현체를 API 핸들러 메소드에 주입하여 요청

3번의 예제

@Target({ElementType.PARAMETER, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal
public @interface CurrentUser {
}

Controller 에서 변환하여 사용

public ResponseEntity<ApiResult> createBoard(
            @RequestBody CreateBoardPayload payload,
            @CurrentUser SimpleUser currentUser) {
...

+ Recent posts