티스토리 뷰

이번 시간에는 3가지 서비스를 한번에 배포하려합니다. 중복되는 내용이니 빠르게 코드만 첨부합니다.


#UserService

#Dockerfile

FROM openjdk:17-ea-11-jdk-slim
VOLUME /tmp
COPY target/userservice-1.0.jar UserService.jar
ENTRYPOINT ["java","-jar","UserService.jar"]

#WebSecurity IP 변경

protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable();
    //http.authorizeRequests().antMatchers("/users/**").permitAll();
    http.authorizeRequests().antMatchers("/actuator/**").permitAll();
    http.authorizeRequests().antMatchers("/**")
            .hasIpAddress("172.18.0.5")
            .and()
            .addFilter(getAuthenticationFilter());


    http.headers().frameOptions().disable();
}

#user-service.yml 변경

spring:
   datasource:
      driver-class-name: org.h2.Driver
      url: jdbc:h2:mem:testdb
      username: sa
      password: '{cipher}AQA3Wlcwu01k0p9/hdLhSv5L/WKKo452yh576T+I/AV5kiNckUu6PBPdmetCB0zecb7AkoktLfqZPt6ziznW3slrKHkIb39vyQjFcn0wKTdp6t38e84uoQbWp5SH7BXsT3pTYrmSwPGDvgr3K3NgPAnfZ0zOntmjR/ImO1YetawqFD3OQUqVxMYB93l6z6lG92vSbZpRRp2tJ9lke1u6zeV+vG3tEeFuezk3nb/r8dk8SGtRjru41tUD/g0fQ9R3Rf/i/0Sly9eN9Q2NAAVJ1Be6ohOMexth1oSQoeKQqmwPVCXxwglpDWvntxfanmsK5oavLeOeglkoXFg9JWVst2A9hJHPke6jyTabzuiz+kv3gHcNrih9bJ9RrEifJ4Xl2a8='
token:
  expiration_time: 864000000
  secret: '{cipher}AQAIOA+faH9XEcX5usyT6e+7ahXOvdmcZtZHMHQyDznJQ21eXzGq11eXqWh7F8/zo2xywBQhSmCz3YbyT181IvPhUB9djzSiYyndedY/k1XX/1lr8a1eZ5QRJbQeuAawgPmeZpr2xb+/7egZw2uUZtzSZKS7xZHh9cXV218sAWteTOKP9Y0AzWuz0ZiV7CJhK9OuZvTBShIlF3Hfy1Umxdmy2AwSqNIEndH8RQer17CaI7fF/sdj41v6YECyL39jP5143aaUyxTt/qgw2RDgh9WrDNdH4LwavG4Pl7+9ob5PDcpZekmScPsXFouJTjGYaX4ICTk04FhoOgxt9ZSB0lBdruNTgzdEaDTE519BaF1EY8noii/4mQDDTIfkX/Gz4oZfHcz6JwhDHeHgKFmxRc4v'
gateway:
  ip: 172.18.0.5

order_service:
  url: http://ORDER-SERVICE/order-service/%s/orders
  exception:
    order_is_empty: hehe ezpz lemonsquizy

#jar file 생성

mvn clean compile package -DskipTests=true

#build Docker file

docker build --tag ggpark0315/user-service:1.0 .

#DockerRun

이제 도커파일을 실행할 예정인데 아래와 같은 커맨드로 실행해주세요. -e 옵션이 많은데 해당 옵션을 설정하는 방법은 저희가 기존에 작성한 application.yml을 보고, 수정해야할 환경설정값 ( ex: config url zipkin url )을 참조해서 설정하시면 됩니다. 마지막 부분은 자신이 생성한 user-service 이미지를 입력해주세여! 

 

docker run -d --network ecommerce-network --name user-service -e "spring.cloud.config.uri=http://config-service:8888" -e "spring.rabbitmq.host=rabbitmq" -e "spring.zipkin.base-url=http://zipkin:9411" -e "eureka.client.serviceUrl.defaultZone=http://discovery-service:8761/eureka/" -e "logging.file=/api-logs/user-ws.log" ggpark0315/user-service2:1.1

#OrderService

#pom.xml 

Version을 1.0으로 바꿔줍니다. 파일명의 길이를 줄여서 생산성을 높히기 위해서 입니다.

<groupId>com.example</groupId>
<artifactId>order-service</artifactId>
<version>1.0</version>
<name>order-service</name>

 

#application.yml

확인위해서 수정했던 datasource부분의 주석을 해제해 줍니다. 아래와 같이요!

datasource:
   url: jdbc:mysql://localhost:3307/mydb
   driver-class-name: org.mariadb.jdbc.Driver
   username: root
   password: test1357

#Kafka

다음으로는 Kafka에서 IP정보를 가져옵니다. 

이유는 KafkaProducerConfig 클래스는 도커에서 수정할 수 없기에 다음과 같이 직접 수정해줘야 하기 때문입니다. 

#172.18.0.101 로 수정 한 KafkaProducerConfig 

package com.example.orderservice.messagequeue;

import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.EnableKafka;
import org.springframework.kafka.core.*;

import java.util.HashMap;
import java.util.Map;

@EnableKafka
@Configuration
public class KafkaProducerConfig {
    @Bean
    public ProducerFactory<String, String> producerFactory() {
        Map<String, Object> properties = new HashMap<>();
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "172.18.0.101:9092");
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);

        return new DefaultKafkaProducerFactory<>(properties);
    }

    @Bean
    public KafkaTemplate<String,String> kafkaTemplate(){
        return new KafkaTemplate<>(producerFactory());
    }
}

#OrderController

다음으로는 Kafka와 연동을 위해 아래와 같이 작성해주세요 코드 전문입니다. 작성된 부분은 없고 주석 해제한 코드입니다.

package com.example.orderservice.controller;

import com.example.orderservice.dto.OrderDto;
import com.example.orderservice.jpa.OrderEntity;
import com.example.orderservice.messagequeue.KafkaProducer;
import com.example.orderservice.messagequeue.OrderProducer;
import com.example.orderservice.service.OrderService;
import com.example.orderservice.vo.RequestOrder;
import com.example.orderservice.vo.ResponseOrder;
import lombok.extern.slf4j.Slf4j;
import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;


@Slf4j
@RestController
@RequestMapping("/order-service")
public class OrderController {
    Environment env;
    OrderService orderService;
    KafkaProducer kafkaProducer;

    OrderProducer orderProducer;

    @Autowired
    public OrderController(Environment env,
                           OrderService orderService,
                           KafkaProducer kafkaProducer,
                           OrderProducer orderProducer){
        this.env = env;
        this.orderService = orderService;
        this.kafkaProducer = kafkaProducer;
        this.orderProducer = orderProducer;
    }
    @PostMapping("/{userId}/orders")
    public ResponseEntity<ResponseOrder> createOrder(@PathVariable("userId") String userId,
                                                    @RequestBody RequestOrder orderDetails){
        log.info("Before create orders data");
        ModelMapper mapper = new ModelMapper();
        mapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);

        OrderDto orderDto = mapper.map(orderDetails, OrderDto.class);
        orderDto.setUserId(userId);

        OrderDto createdOrder = orderService.createOrder(orderDto);
        ResponseOrder responseOrder = mapper.map(createdOrder,ResponseOrder.class);

//        /*kafka*/
//        orderDto.setOrderId(UUID.randomUUID().toString());
//        orderDto.setTotalPrice(orderDetails.getQty() * orderDetails.getUnitPrice());
//
//        /* send this order */
        kafkaProducer.send("example-catalog-topic",orderDto);
//        orderProducer.send("orders", orderDto);
//
//
//        ResponseOrder responseOrder = mapper.map(orderDto,ResponseOrder.class);
        log.info("Create orders data");
        return ResponseEntity.status(HttpStatus.CREATED).body(responseOrder);

    }
    @GetMapping("/{userId}/orders")
    public ResponseEntity<List<ResponseOrder>> getOrder(@PathVariable("userId") String userId) throws Exception{
        log.info("Before retrieve orders data");
        Iterable<OrderEntity> orderList = orderService.getOrdersByUserId(userId);

        List<ResponseOrder> result = new ArrayList<>();
        orderList.forEach(v->{
            result.add(new ModelMapper().map(v,ResponseOrder.class));
        });

//        try{
//            Thread.sleep(1000);
//            throw new Exception("엄...");
//        }catch(InterruptedException ex){
//            log.warn(ex.getMessage());
//        }
        log.info("Add retrieved orders data");
        return ResponseEntity.status(HttpStatus.OK).body(result);
    }

}

 

#jar file build

mvn clean package -DskipTests=true

#Dockerfile

FROM openjdk:17-ea-11-jdk-slim
VOLUME /tmp
COPY target/order-service-1.0.jar OrderService.jar
ENTRYPOINT ["java","-jar","OrderService.jar"]

#Docker build

docker build --tag ggpark0315/order-service:1.0 .

#Push 

docker push ggpark0315/order-service:1.0

#Docker run

docker run -d --network ecommerce-network --name order-service -e "spring.cloud.config.uri=http://config-service:8888" -e "spring.rabbitmq.host=rabbitmq" -e "spring.zipkin.base-url=http://zipkin:9411" -e "spring.datasource.url=jdbc:mariadb://mariadb:3306/mydb" -e "eureka.client.serviceUrl.defaultZone=http://discovery-service:8761/eureka/" -e "logging.file=/api-logs/order-ws.log" ggpark0315/order-service:1.0

이슈노트

대부분 호스트 문제로 접속이 안될 확률이 높습니다. 그래서 MariaDB에 직접 접속을 통해 권한을 부여해야 합니다. 커맨드에서 아래의 순서로 모든 포트에 권한을 부여해줍니다.

docker exec -it mariadb /bin/bash

mysql -h127.0.0.1 -uroot -p

//Enter Password

use mysql;

grant all privileges on *.* to 'root'@'%' identified by 'test1357';

flush privileges;

exit

 

#정상 구동 시

🍯작은 꿀통🍯

만약 컨테이너가 너무 꼬인다면 exited된 컨테이너는 다 지워버리는 커맨드에요!

docker ps -a -q -f status=exited

 


#CatalogService 

 

#pom.xml

<groupId>com.example</groupId>
<artifactId>catalog-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>catalog-service</name>

#KafkaConsumerConfig

ip값만 변경해줍니다.

@Bean
public ConsumerFactory<String,String> consumerFactory(){
    Map<String,Object> properties = new HashMap<>();
    properties.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG,"172.18.0.101:9092");
    properties.put(ConsumerConfig.GROUP_ID_CONFIG,"consumerGroupId");
    properties.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
    properties.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,StringDeserializer.class);
    return new DefaultKafkaConsumerFactory<>(properties);
}

 

#jar file build

mvn clean compile package -DskipTests=true

#Docker build

docker build --tag ggpark0315/catalog-service:1.0 .

#Docker push

docker push ggpark0315/catalog-service:1.0

#Docker run

docker run -d --network ecommerce-network --name catalog-service -e "spring.cloud.config.uri=http://config-service:8888" -e "spring.rabbitmq.host=rabbitmq" -e "eureka.client.serviceUrl.defaultZone=http://discovery-service:8761/eureka/" -e "logging.file=/api-logs/catalogs-ws.log" ggpark0315/catalog-service:1.0

모든 서비스를 Container 기동에 성공하셨다면, 아래의 주소로 접속해주세요

#127.0.0.1:8761  

드디어 배포 작업까지 끝이 났습니다. 마지막 작업이었지만, 사실 중복작업이라 쓸말이 별로 없었습니다. 짧다면 짧고 길다면 긴 포스팅 이었고, 처음보다 훨씬많이 발전한 거 같아 기분이 좋습니다. 아직 걸음마를 뗐을 뿐이지만, 끝났다는 해방감이 기쁘네요. 혹시라도 나중에 제 글을 처음부터 같이 따라오신 분이 계시다면 저와 같은 기분일지도 모르겠습니다. 그럼 다음 포스팅에는 마지막으로 테스트를 하며 가벼운 마음으로 끝내도록 하겠습니다!!!

 

감사합니다

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함