β κΉνλΈ μμ€μ½λ
β Udemy κ°μ
Β Β Β Β @HystrixCommand
κ° μ€νλ λ THREAD
μ SEMAPHORE
λΌλ λ κ°μ§ λ€λ₯Έ 격리 μ λ΅μ μνν μ μμ΅λλ€. κΈ°λ³Έμ μΌλ‘ νμ€νΈλ¦μ€λ THREAD
격리 μ λ΅μ μνν©λλ€. νΈμΆμ 보νΈνλ λ° μ¬μ©λ λͺ¨λ νμ€νΈλ¦μ€ λͺ
λ Ήμ νΈμΆμ μλν λΆλͺ¨ μ€λ λμ 컨ν
μ€νΈλ₯Ό 곡μ νμ§ μλ 격리λ μ€λ λ νμμ μνλ©λλ€. μ΄λ νμ€νΈλ¦μ€κ° μκΈ° ν΅μ νμμ μλ νΈμΆμ μλν λΆλͺ¨ μ€λ λμ μ°κ΄λ μ΄λ€ νλλ λ°©ν΄νμ§ μκ³ μ€λ λ μ€νμ μ€λ¨ν μ μλ€λ κ²μ μλ―Έν©λλ€.
Β Β Β Β λ°λ©΄μ SEMAPHORE
κΈ°λ° κ²©λ¦¬ λ°©λ²μ μ¬μ©νλ©΄ νμ€νΈλ¦μ€λ μλ‘μ΄ μ€λ λλ₯Ό μμνμ§ μκ³ @HystrixCommand
μ΄λ
Έν
μ΄μ
μ΄ λ³΄νΈνλ λΆμ° νΈμΆμ κ΄λ¦¬νλ©° νμ μμμ΄ λ°μνλ©΄ λΆλͺ¨ μ€λ λλ₯Ό μ€λ¨μν΅λλ€. Tomcat μ²λΌ λκΈ°μ 컨ν
μ΄λ μλ² νκ²½μμ λΆλͺ¨ μ€λ λλ₯Ό μ€λ¨νλ©΄ κ°λ°μκ° μμΈ μ²λ¦¬λ₯Ό ν μ μλ μμΈκ° λ°μν©λλ€. μ΄μ²λΌ λ°μν μμΈλ₯Ό μ²λ¦¬ν μ μκ±°λ μμ μ 리 λ° μλ¬ μ²λ¦¬λ₯Ό μνν μ μλ€λ©΄ κ°λ°μκ° μ½λλ₯Ό μμ±ν λ μμνμ§ λͺ»ν κ²°κ³Όκ° λ°μν μ μμ΅λλ€.
β λͺ λ Ή νμ λν 격리 μ€μ λ°©λ²
@HystrixCommand(
commandProperties = {
@HystricProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")
}
)
public void someMethod() {}
β NOTE
Β Β Β Β κΈ°λ³Έμ μΌλ‘ λλΆλΆμ λͺ
λ Ήμ λν΄ κΈ°λ³Έ 격리 μ λ΅μΈ THREAD
λ°©μμ κΆμ₯ν©λλ€. THREAD
격리 λ°©μμ νμ€νΈλ¦μ€ λͺ
λ Ή μ€λ λμ λΆλͺ¨ μ€λ λ μ¬μ΄μ 격리 μμ€μ λμ΄λ©°, SEMAPHORE
격리 λ°©μλ³΄λ€ λ¬΄κ²μ΅λλ€. SEMAPHORE
격리 λͺ¨λΈμ 격λμ΄λ©°, μλΉμ€μμ λμ©λμ μ²λ¦¬νκ³ λΉλκΈ° I/O νλ‘κ·Έλλ° λͺ¨λΈμ μ μ©ν λ μ¬μ©ν΄μΌ ν©λλ€.
Β Β Β Β κΈ°λ³Έμ μΌλ‘ νμ€νΈλ¦μ€λ λΆλͺ¨ μ€λ λμ 컨ν
μ€νΈλ₯Ό νμ€νΈλ¦μ€ λͺ
λ Ήμ΄ κ΄λ¦¬νλ μ€λ λμ μ ννμ§ μμ΅λλ€. μλ₯Ό λ€μ΄ λΆλͺ¨ μ€λ λμμ ThreadLocal
λ‘ μ€μ λ κ°μ κΈ°λ³Έμ μΌλ‘ λΆλͺ¨ μ€λ λκ° νΈμΆνλ λ©μλμμ μ¬μ©ν μ μκ³ @HystrixCommand
κ°μ²΄λ‘ 보νΈλ©λλ€.
Β Β Β Β REST κΈ°λ° νκ²½μμ μ’ μ’ μλΉμ€λ₯Ό μ΄μ κ΄λ¦¬νλ λ° λμμ΄ λλ 컨ν μ€νΈ κ΄λ ¨ μ 보λ₯Ό μλΉμ€ νΈμΆλ‘ μ λ¬νλ κ²½μ°κ° μμ΅λλ€. μλ₯Ό λ€μ΄ HTTP Headerμ μκ΄ κ΄κ³ ID(Correlation ID)λ μΈμ¦ ν ν°μ λ΄μ μ λ¬ν ν λͺ¨λ νμ μλΉμ€ νΈμΆμ μ νν μ μμ΅λλ€. μ¬κΈ°μ μκ΄ κ΄κ³ IDλ₯Ό μ¬μ©νλ©΄ ν νΈλμμ λ΄ μ¬λ¬ μλΉμ€ νΈμΆμ μΆμ ν μ μλ κ³ μ ν μλ³μ(ID)λ₯Ό κ°κ² λ©λλ€.
Β Β Β Β μ΄ κ°λ€μ λͺ¨λ μλΉμ€ νΈμΆμ μ¬μ©ν μ μκ² νλ €λ©΄ μ€νλ§ νν°(Spring Filter)
ν΄λμ€λ₯Ό μ¬μ©ν΄ REST μλΉμ€μ λν λͺ¨λ νΈμΆμ κ°λ‘μ±κ³ , λ€μ΄μ€λ HTTP μμ²μμ 컨ν
μ€νΈ μ 보λ₯Ό μΆμΆν΄ μ¬μ©μ μ μν UserContext
κ°μ²΄μ μ μ₯ν μ μμ΅λλ€.
β μ€νλ§ νν° μμ μ½λ
@Component
public class UserContextFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(UserContextFilter.class);
/**
*
* HTTP Request Headerμμ κ²μν κ°μ UserContextHolderμ UserContextμ μ μ₯νλ€.
*
*/
@Override
public void doFilter(
ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain
) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
UserContextHolder.getContext().setCorrelationId(httpServletRequest.getHeader(UserContext.CORRELATION_ID));
UserContextHolder.getContext().setUserId(httpServletRequest.getHeader(UserContext.USER_ID));
UserContextHolder.getContext().setAuthToken(httpServletRequest.getHeader(UserContext.AUTH_TOKEN));
UserContextHolder.getContext().setOrgId(httpServletRequest.getHeader(UserContext.ORG_ID));
logger.debug("UserContextFilter Correlation id: {}", UserContextHolder.getContext().getCorrelationId());
filterChain.doFilter(httpServletRequest, servletResponse);
}
}
UserContextHolder
ν΄λμ€λ ThreadLocal
ν΄λμ€μ UserContext
λ₯Ό μ μ₯νλ λ° μ¬μ©λ©λλ€. UserContext
κ° ThreadLocal
μ μ₯μμ μ μ₯λλ©΄ μμ²μΌλ‘ μ€νλ λͺ¨λ μ½λμμ UserContextHolder
μ UserContext
κ°μ²΄λ₯Ό μ¬μ©ν μ μμ΅λλ€.
β UserContextHolder & UserContext μμ μ½λ
public class UserContextHolder {
// μ μ ThreadLocal λ³μμ μ μ₯λλ UserContext
private static final ThreadLocal<UserContext> userContext = new ThreadLocal<UserContext>();
public static UserContext getContext() {
UserContext context = userContext.get();
if(context == null) {
context = createEmptyContext();
userContext.set(context);
}
return userContext.get();
}
public static void setContext(UserContext context) {
Assert.notNull(context, "Only non-null UserContext instances are permitted.");
userContext.set(context);
}
public static UserContext createEmptyContext() {
return new UserContext();
}
}
@Component
@Getter
@Setter
public class UserContext {
public static final String CORRELATION_ID = "spmia-correlation-id";
public static final String AUTH_TOKEN = "spmia-auth-token";
public static final String USER_ID = "spmia-user-id";
public static final String ORG_ID = "spmia-org-id";
private String correlationId = "";
private String authToken = "";
private String userId = "";
private String orgId = "";
}