본문 바로가기
▶ Back-End/Java

GPU 작업 관리 예제 - GMS-WAS

by 오늘도 코딩 2025. 1. 21.
728x90
반응형

Redis 큐 기반 GPU 별 작업 할당 및 처리

*자세한 설명 생략

 

 

▷ 시스템 구성도

 

 

▷ 프로젝트 구조

*필요한 부분만 필터링

 

 

 < 파일 따라가기 >

*순서대로 나열

 

▷ RedisConfig.java

▷ TaskManager.java

▷ IMG1000Controller.java

▷ IMGServiceImpl.java

▷ IMGService.java

▷ application.properties

 

 

 

 

 

 

 

 

 

▷ RedisConfig.java

package gms.cmm.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

import gms.cmm.util.TaskManager;

/**
 * Redis Config
 */
@Configuration
public class RedisConfig {

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Autowired
    private TaskManager taskManager;

    @Value("${redis.subscribe.channel}")
    private String SUBSCRIBE_CHANNEL;

    /**
     * Redis 구독 설정
     */
    @Bean
    public RedisMessageListenerContainer redisMessageListenerContainer() {

        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(redisConnectionFactory);
        container.addMessageListener(messageListener(), new ChannelTopic(SUBSCRIBE_CHANNEL));

        return container;
    }

    /**
     * Redis 메시지 리스너
     */
    private MessageListener messageListener() {
        return new MessageListener() {

            @Override
            public void onMessage(Message message, byte[] pattern) {
                byte[] resultData = message.getBody();
                taskManager.setResultData(resultData);
            }
        };
    }
}

 

 

▷ TaskManager.java

package gms.cmm.util;

import java.util.UUID;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import lombok.RequiredArgsConstructor;

/**
 * Task Manager
 */
@Component
@RequiredArgsConstructor
public class TaskManager {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final Lock lock = new ReentrantLock();

    private byte[] resultData;

    /**
     * Lock 객체
     * 
     * <pre>
     *  - 여러 스레드가 동시에 자원에 접근하지 않도록 동기화
     * </pre>
     */
    public Lock getLock() {
        return lock;
    }

    /**
     * Redis 큐 추가
     * 
     * @param queueName
     */
    public void addTaskToQueue(String queueName) {
        String requestId = UUID.randomUUID().toString();
        redisTemplate.opsForList().leftPush(queueName, requestId);
    }

    /**
     * 결과 데이터 반환
     * 
     * @return
     */
    public byte[] getResultData() {
        return resultData;
    }

    /**
     * 대기 중인 스레드에 작업 완료 알림
     * 
     * @param resultData
     */
    public void setResultData(byte[] resultData) {
        synchronized (lock) {
            this.resultData = resultData;
            lock.notify();
        }
    }
}

 

 

▷ IMG1000Controller.java

package gms.gms.img.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import gms.cmm.api.CmmController;
import gms.cmm.util.CmmUtil;
import gms.gms.img.service.IMGService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;

/**
 * Image 서비스 Controller
 */
@RestController
@RequestMapping("img")
@Tag(name = "IMAGE", description = "IMAGE 서비스")
@Slf4j
public class IMG1000Controller extends CmmController {

    @Autowired
    private IMGService imgService;

    @GetMapping("/img1000.do")
    @Operation(summary = "IMG-1000", description = "이미지 생성")
    public ResponseEntity<?> IMG1000() {
        final String title = "IMG-1000";

        ResponseEntity<byte[]> resVO = new ResponseEntity<>(HttpStatus.OK);

        try {

            resVO = imgService.getIMG1000();

            if (resVO.getBody() == null) {
                return ResponseEntity.status(500).build();
            }

            
        } catch (Exception e) {
            CmmUtil.errLogStamp(title, e);
            return ResponseEntity.status(500).build();
        }

        return resVO;
    }
}

 

 

▷ IMGServiceImpl.java

package gms.gms.img.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import gms.cmm.util.TaskManager;
import gms.gms.img.service.IMGService;
import lombok.extern.slf4j.Slf4j;

/**
 * Image 서비스 Impl
 */
@Service
@Slf4j
public class IMGServiceImpl implements IMGService {

    @Autowired
    private TaskManager taskManager;

    @Value("${redis.img.queue}")
    private String IMG_QUEUE;

    /**
     * IMG-1000: 이미지생성
     */
    @Override
    public ResponseEntity<byte[]> getIMG1000() {

        try {

            // 작업 큐 추가
            taskManager.addTaskToQueue(IMG_QUEUE);

            // GPU 서버가 작업을 완료할 때까지 대기
            synchronized (taskManager.getLock()) {
                taskManager.getLock().wait();
            }

            // 작업 완료
            byte[] resultData = taskManager.getResultData();
            log.info(resultData+"");
            if (resultData == null) {
                return ResponseEntity.status(500).build();
            }

            // 결과 이미지 반환
            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE)
                    .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=image.png")
                    .body(resultData);

        } catch (Exception e) {
            log.error("getIMG1000 Err: " + e.getMessage(), e);
            return ResponseEntity.status(500).build();
        }
    }
}

 

 

▷ IMGService.java

package gms.gms.img.service;

import org.springframework.http.ResponseEntity;

/**
 * Image 서비스
 */
public interface IMGService {

    /** IMG-1000: 이미지생성 */
    public ResponseEntity<byte[]> getIMG1000();
}

 

 

▷ application.properties

## Server
server.port=9999

# Redis
spring.data.redis.url=redis://127.0.0.1:6379
redis.subscribe.channel=gpu_channel
redis.img.queue=gpu_image

 

 

▷ 관련 글

 

Lock 이란?

여러 스레드가 독립적으로 작업을 처리하는 환경에서 작업의 안정성과 효율성을 보장*자세한 설명 생략  ▷ Lock 이란     - 스레드가 동시에 작업을 처리하는 환경에서 동기화를 통해 작업의

coding-today.tistory.com

 

GPU 작업 관리 예제 - GMS-CORE

Redis 큐 기반 GPU 별 작업 할당 및 처리*자세한 설명 생략  ▷ 시스템 구성도  ▷ 프로젝트 구조*순서대로 나열 ▷ const.py▷ redis_config.py▷ gpu_batch_service.py▷ gpu_service.py▷ logger.py▷ main.py  ▷ co

coding-today.tistory.com

 

GPU 작업 관리 예제 - 배포 및 결과 확인

Redis 큐 기반 GPU 별 작업 할당 및 처리*자세한 설명 생략  ▷ 시스템 구성도  ▷ Redis 설치 및 구동*Docker에서 간단하게 설치해서 사용# Redis Docker 이미지 다운로드docker pull redis:7.0.11# Redis 컨테이

coding-today.tistory.com

 

 

728x90
728x90

'▶ Back-End > Java' 카테고리의 다른 글

Get Add Time(HHH:mm:ss)  (0) 2024.11.27
Get Convert HHH:mm:ss to Second  (0) 2024.11.27
Get Convert Second to HHH:mm:ss  (0) 2024.11.27
Get Days Between Count  (0) 2024.11.27
Get Date Now in String  (0) 2024.11.27

댓글