'config'에 해당되는 글 9건

  1. 2020.06.25 [Spring] Spring Cloud Config 설정 파일 적용
  2. 2020.06.18 [Spring] Spring Cloud Config 다중 Backend 사용 시...
  3. 2020.06.16 [Spring] @RefreshScope 적용 시 반영이 잘 안될 때
  4. 2020.04.21 [Spring] Spring Cloud Config Client 구성 시 주의점
  5. 2020.03.26 [AWS] Spring Cloud Config S3 Backend 사용하기
  6. 2018.10.04 [Logstash] --config.reload.automatic 사용 경험 공유
  7. 2017.02.07 [HttpClient] Timeout 설정 예시
  8. 2016.02.12 [Logstash] Dynamic Config Reloading
  9. 2012.05.22 [C언어] 설정파일 읽기

[Spring] Spring Cloud Config 설정 파일 적용

ITWeb/개발일반 2020. 6. 25. 14:29

spring config client  에 server config 파일이 존재 할 경우 적용 안되는 문제를 해결 하기 위해 아래 설정을 하면 됩니다.

 

https://cloud.spring.io/spring-cloud-static/spring-cloud-commons/2.2.2.RELEASE/reference/html/#overriding-bootstrap-properties

 

1.4. Overriding the Values of Remote Properties

The property sources that are added to your application by the bootstrap context are often “remote” (from example, from Spring Cloud Config Server). By default, they cannot be overridden locally. If you want to let your applications override the remote properties with their own system properties or config files, the remote property source has to grant it permission by setting spring.cloud.config.allowOverride=true (it does not work to set this locally). Once that flag is set, two finer-grained settings control the location of the remote properties in relation to system properties and the application’s local configuration:

  • spring.cloud.config.overrideNone=true: Override from any local property source.

  • spring.cloud.config.overrideSystemProperties=false: Only system properties, command line arguments, and environment variables (but not the local config files) should override the remote settings.

spring:
  cloud:
    config:
      uri: xxxx
      allowOverride: true
      overrideNone: true
      overrideSystemProperties: false

 

Trackbacks 0 : Comments 0

Write a comment


[Spring] Spring Cloud Config 다중 Backend 사용 시...

ITWeb/개발일반 2020. 6. 18. 10:41

Spring Cloud Config 를 이용해서 다중 Backend 를 구성 할 수 있습니다.

그러나 order 옵션이 저는 제대로 동작 하지 않아서 실행 시 사용해야 하는 Backend 에 대한 profile 로 관리하기로 했습니다.

 

동시에 두 개의 Backend 를 사용 하는 것도 가능 한데 이게 같은 설정 파일이 양쪽에 다 존재 할 때 order 에 맞춰서 설정 정보를 가져 와야 하는데 이상하게도 git 에 있는 설정을 먼저 가져 와서 목적에 맞게 사용을 할 수 없었습니다.

 

spring:
  application:
    name: config-server
  profiles:
    active: awss3, git
  cloud:
    config:
      server:
        awss3:
          region: ap-northeast-2
          bucket: ${BUCKET-NAME}
          order: 1
        git:
          uri: https://git/config-repo.git
          skipSslValidation: true
          username: xxxxx
          password: xxxxx
          clone-on-start: true
          order: 2

저렇게 설정 하고 했었는데 잘 못된 부분이 있다면 댓글 좀 달아 주세요. :)

 

profile을 실행 시점에 awss3 나 git 으로 설정해서 사용 하도록 마무리 했습니다.

Trackbacks 0 : Comments 0

Write a comment


[Spring] @RefreshScope 적용 시 반영이 잘 안될 때

ITWeb/개발일반 2020. 6. 16. 14:51

일단 spring config server 에서 설정을 변경해서 적용 합니다.

 

POST , /actuator/refresh 를  실행 합니다.

 

그럼 기대 하는 건 변경 된 설정 값이 반영이 되어 있어야 한다는 것입니다.

 

그러나 반영이 안되어 있어서 디버깅 하다 아래와 같이 event 를 잡아서 처리를 해주니 잘되는 것을 확인 했습니다.

 

  @EventListener(RefreshScopeRefreshedEvent.class)
  public void onRefresh() {
    log.debug("triggering ----> {}", watcherThreshold);
  }

참고해서 보셔야 하는 코드는 아래 입니다.

/*
 * Copyright 2012-2020 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.cloud.context.scope.refresh;

import java.io.Serializable;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.cloud.context.scope.GenericScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.Ordered;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;

/**
 * <p>
 * A Scope implementation that allows for beans to be refreshed dynamically at runtime
 * (see {@link #refresh(String)} and {@link #refreshAll()}). If a bean is refreshed then
 * the next time the bean is accessed (i.e. a method is executed) a new instance is
 * created. All lifecycle methods are applied to the bean instances, so any destruction
 * callbacks that were registered in the bean factory are called when it is refreshed, and
 * then the initialization callbacks are invoked as normal when the new instance is
 * created. A new bean instance is created from the original bean definition, so any
 * externalized content (property placeholders or expressions in string literals) is
 * re-evaluated when it is created.
 * </p>
 *
 * <p>
 * Note that all beans in this scope are <em>only</em> initialized when first accessed, so
 * the scope forces lazy initialization semantics.
 * </p>
 *
 * <p>
 * The scoped proxy approach adopted here has a side benefit that bean instances are
 * automatically {@link Serializable}, and can be sent across the wire as long as the
 * receiver has an identical application context on the other side. To ensure that the two
 * contexts agree that they are identical, they have to have the same serialization ID.
 * One will be generated automatically by default from the bean names, so two contexts
 * with the same bean names are by default able to exchange beans by name. If you need to
 * override the default ID, then provide an explicit {@link #setId(String) id} when the
 * Scope is declared.
 * </p>
 *
 * @author Dave Syer
 * @since 3.1
 *
 */
@ManagedResource
public class RefreshScope extends GenericScope implements ApplicationContextAware,
		ApplicationListener<ContextRefreshedEvent>, Ordered {

	private ApplicationContext context;

	private BeanDefinitionRegistry registry;

	private boolean eager = true;

	private int order = Ordered.LOWEST_PRECEDENCE - 100;

	/**
	 * Creates a scope instance and gives it the default name: "refresh".
	 */
	public RefreshScope() {
		super.setName("refresh");
	}

	@Override
	public int getOrder() {
		return this.order;
	}

	public void setOrder(int order) {
		this.order = order;
	}

	/**
	 * Flag to determine whether all beans in refresh scope should be instantiated eagerly
	 * on startup. Default true.
	 * @param eager The flag to set.
	 */
	public void setEager(boolean eager) {
		this.eager = eager;
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
			throws BeansException {
		this.registry = registry;
		super.postProcessBeanDefinitionRegistry(registry);
	}

	@Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
		start(event);
	}

	public void start(ContextRefreshedEvent event) {
		if (event.getApplicationContext() == this.context && this.eager
				&& this.registry != null) {
			eagerlyInitialize();
		}
	}

	private void eagerlyInitialize() {
		for (String name : this.context.getBeanDefinitionNames()) {
			BeanDefinition definition = this.registry.getBeanDefinition(name);
			if (this.getName().equals(definition.getScope())
					&& !definition.isLazyInit()) {
				Object bean = this.context.getBean(name);
				if (bean != null) {
					bean.getClass();
				}
			}
		}
	}

	@ManagedOperation(description = "Dispose of the current instance of bean name "
			+ "provided and force a refresh on next method execution.")
	public boolean refresh(String name) {
		if (!name.startsWith(SCOPED_TARGET_PREFIX)) {
			// User wants to refresh the bean with this name but that isn't the one in the
			// cache...
			name = SCOPED_TARGET_PREFIX + name;
		}
		// Ensure lifecycle is finished if bean was disposable
		if (super.destroy(name)) {
			this.context.publishEvent(new RefreshScopeRefreshedEvent(name));
			return true;
		}
		return false;
	}

	@ManagedOperation(description = "Dispose of the current instance of all beans "
			+ "in this scope and force a refresh on next method execution.")
	public void refreshAll() {
		super.destroy();
		this.context.publishEvent(new RefreshScopeRefreshedEvent());
	}

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		this.context = context;
	}

}

 

refreshAll() 을 호출 하게 되어서 반영이 잘됩니다.

 

더불어 그냥 프레임워크에서 제공하는 @Scheduled 사용 하십시오.

 

  @Scheduled(fixedDelayString = "${megatoi.watcher.cpu.period}000")
  private void runner() {
    megatoiCheckerUtil.setWatcherThreshold(watcherThreshold);
    megatoiCheckerUtil.setPayload(getCheckQuery());
    megatoiCheckerUtil.setResourceType(ResourceType.CPU);
    megatoiCheckerUtil.commonRunner();
  }
Trackbacks 0 : Comments 0

Write a comment


[Spring] Spring Cloud Config Client 구성 시 주의점

ITWeb/개발일반 2020. 4. 21. 16:35

주의점 이라기 보다 그냥 설정을 잘 못 하는 경우가 있어서 기록 합니다.

 

Client 쪽 Dependency 등록)

implementation 'org.springframework.cloud:spring-cloud-starter-config'
implementation 'org.springframework.boot:spring-boot-starter-actuator'

 

Client 쪽 bootstrap.yml 등록)

spring:
  cloud:
    config:
      uri: http://${CONFIG_SERVER_HOST}:${PORT}

management:
  endpoints:
    web:
      exposure:
        include: refresh

 

Refresh 호출)

- HTTP Method : POST

- http://${CONFIG_CLIENT_HOST}:${PORT}/actuator/refresh

 

bootstrap.yml 에 등록 하지 않게 되면 client 가 config server 를 localhost:8888 로 찾는 오류가 발생 할 수 있습니다.

또한 refresh 등록을 해줘야 actuator/refresh 사용이 가능 합니다.

 

Trackbacks 0 : Comments 0

Write a comment


[AWS] Spring Cloud Config S3 Backend 사용하기

Cloud&Container/AWS 2020. 3. 26. 10:57

Spring Cloud Config Server 설정)

 

[S3 설정]
- S3 버킷 생성
- 접근권한 부여

[ConfigApplication.java]

@SpringBootApplication
@EnableConfigServer
public class ConfigApplication {
  public static void main(String[] args) {
	SpringApplication.run(ConfigApplication.class, args);
  }
}


[build.gradle]

compile 'com.amazonaws:aws-java-sdk-s3'


[application.yml]

server:
port: 8888

spring:
  profiles:
    active: awss3
  cloud:
    config:
      server:
        awss3:
          region: ap-northeast-2
          bucket: s3config


[Config Server 접근 URL]

http://localhost:8888/${S3-FILE-NAME}/${PROFILE-NAME}

- 생성한 버킷 하위로 설정 파일 목록이 존재 해야 합니다.
- ${S3-FILE-NAME} 는 생성한 Bucket 아래 만든 설정 파일명 입니다.
- backoffice
- ${PROFILE-NAME} 은 설정 파일에 대한 프로필명 입니다.
- app1, app2

예제)
Config Server URL : 
http://localhost:8888/backoffice/app1

S3 :
megatoidiscons3config/backoffice-app1.yml
or
megatoidiscons3config/backoffice-app1.properties


[backoffice-app1.yml]

project.app1="backoffice-app1"


[backoffice-app2.yml]

project.app2="backoffice-app2"

 

Spring Cloud Config Client 설정)

[application.yml]

spring:
  cloud:
    config:
      name: backoffice
      uri: http://localhost:8888
      profile: app1,app2


[HelloController.java]

@RestController
public class HelloController {

  @Value ("${project.app1}")
  String projectApp1;

  @Value ("${project.app2}")
  String projectApp2;

  @RequestMapping("/app1")
  public String helloApp1() {
    return projectApp1;
  }

  @RequestMapping("/app2")
  public String helloApp2() {
    return projectApp2;
  }
}

 

git 사용 하는 건 문서들이 많이 나와 있어서 s3 로 정리해 봤습니다.

Trackbacks 0 : Comments 0

Write a comment


[Logstash] --config.reload.automatic 사용 경험 공유

Elastic/Logstash 2018. 10. 4. 11:28

Logstash 사용 시 --config.reload.automatic 설정을 통해서 conf 파일에 대한 변경 사항을 데몬 재시작 없이 할 수 있습니다.

하지만 모든 변경 사항에 대해서 반영이 가능 하지 않기 때문에 사용 시 주의 하셔야 합니다.


크게 사용 방법은 두 가지로 나뉩니다.

1. --config.reload.automatic 을 통한 자동 갱신

2. Logstash 재시작을 통한 갱신


2번의 과정을 하고 싶지 않기 때문에 1번을 설정해서 사용을 하는데 문제는 이게 모든 plugins 에서 동작 하지는 않는 다는 것입니다.


만약 아래와 같은 에러를 접하셨다면, 해당 plugin 또는 pipeline 은 auto reload 설정이 동작 하지 않는 것들 이니 참고 하시기 바랍니다.


[에러내용]

[ERROR][logstash.agent           ] Failed to execute action {:id=>:main, :action_type=>LogStash::ConvergeResult::FailedAction, :message=>“Cannot reload pipeline, because the existing pipeline is not reloadable”, :backtrace=>nil}


쉽게는 기본적인 syntax 오류 같은건 바로 바로 반영 됩니다. :)

Trackbacks 0 : Comments 0

Write a comment


[HttpClient] Timeout 설정 예시

ITWeb/개발일반 2017. 2. 7. 13:41

HttpClient를 사용하면서 간혹 read timeout 이나 connection timeout 등이 발생 할 때가 있습니다.

그럴때 값을 조정해서 사용하시면 됩니다.


- 문서링크

setConnectionRequestTimeout

public RequestConfig.Builder setConnectionRequestTimeout(int connectionRequestTimeout)


setConnectTimeout

public RequestConfig.Builder setConnectTimeout(int connectTimeout)


setSocketTimeout

public RequestConfig.Builder setSocketTimeout(int socketTimeout)



아래 예시는 10초로 설정한 내용입니다.

HttpPost request = new HttpPost(url);


RequestConfig requestConfig = RequestConfig.custom()

  .setSocketTimeout(10*1000)

  .setConnectTimeout(10*1000)

  .setConnectionRequestTimeout(10*1000)

  .build();


request.setConfig(requestConfig);


Trackbacks 0 : Comments 0

Write a comment


[Logstash] Dynamic Config Reloading

Elastic/Logstash 2016. 2. 12. 10:57

예전에도 있던 기능 이였는지는 잘 모르겠습니다.

그래서 기록해 봅니다.


원문링크)


한 줄 요약)

--auto-reload --reload-interval 옵션을 통해 logstash 재시작 없이 설정 적용이 가능 합니다.


명령어 예시)

bin/logstash -f config_file --auto-reload --reload-interval 2

※ 원문에 나와 있는 예시 입니다.

※ 기본 reload interval 은 3초로 정의 되어 있습니다.


이 기능을 제공하는 Version은 logstash 2.2 이상 입니다.

Trackbacks 0 : Comments 0

Write a comment


[C언어] 설정파일 읽기

ITWeb/개발일반 2012. 5. 22. 23:17

[Build & Run]

gcc -c config.c; gcc config.o -o config

./config /home/jjeong/workspace/config/config.property

[config.property]

# UserAuthUrl
UserAuthUrl^http://192.168.1.2:8080/rcpt_auth?email=%s
# UserAuthCompareStr
UserAuthCompareStr^verified
# DlAuthUrl
DlAuthUrl^http://192.168.1.2:8080/dlCheck?q={filterSearch:'%s'}
# DlAuthCompareStr
DlAuthCompareStr^SUCCESS
# AhfServer
AhfServer^192.168.1.2
# AhfPort
AhfPort^33000
#AhfUser
AhfUser^jjeong
#AhfPass
AhfPass^1234
#AhfDb
AhfDb^demodb
#AhfQuery
AhfQuery^SELECT * FROM event WHERE id='%s'
#SkipDomain
SkipDomain^jjeong.com

[config.c]

#include <stdio.h>

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef struct config {
        char userAuthUrl[256];
        char userAuthCompareStr[128];
        char dlAuthUrl[256];
        char dlAuthCompareStr[128];
        char ahfServer[128];
        int ahfPort;
        char ahfUser[128];
        char ahfPass[128];
        char ahfDb[128];
        char ahfQuery[128];
        char skipDomain[128];
} CONFIG;

int isBlank(char ch) {
    return ( (ch==0x20) || (ch=='\t') || (ch=='\r') || (ch=='\n') );
}

char *trim( char *s ) {
    char *f=s, *e=0, *c=s;

    /* 뒤쪽 공백 제거 */
    e=s +(strlen(s)) -1;
    while( isBlank(*e) && s<=e) e--;
    *(e+1)=0;

    /* 앞쪽 공백 제거 */
    while( isBlank(*f) && f<=e) f++;

    /* 공백 없는 부분 복사 */
    if (s!=f) {
        while(f<=e) *(c++) = *(f++);
        *c=0;
    }

    return s;
}

int setConfig(CONFIG *conf, char *confFile) {
        char readBuff[512];
        char varBuff[256];
        char *temp;

        FILE *fp;

        memset(varBuff, 0, 256);

        fp = fopen(confFile, "r");

        if ( fp ){
                while ( !feof(fp) ) {
                        memset(readBuff, 0, 512);

                        if ( fgets(readBuff, 512, fp) == NULL ) {
                                continue;
                        }

                        temp = trim(readBuff);

                        if ( *temp == '#' ) {
                                continue;
                        }

                        if ( strncasecmp(temp, "UserAuthUrl", strlen("UserAuthUrl")) == 0 ) {
                                strcpy(conf->userAuthUrl, strrchr(temp, '^')+1);
                                snprintf(varBuff, sizeof(varBuff), conf->userAuthUrl, "sadfasdfsafasfsdafsafsadf");
                                printf("UserAuthUrl : %s\n", varBuff);
                                memset(varBuff, 0, 256);
                        }

                        if ( strncasecmp(temp, "UserAuthCompareStr", strlen("UserAuthCompareStr")) == 0 ) {
                                strcpy(conf->userAuthCompareStr, strrchr(temp, '^')+1);
                                printf("UserAuthCompareStr : %s\n", conf->userAuthCompareStr);
                        }

                        if ( strncasecmp(temp, "DlAuthUrl", strlen("DlAuthUrl")) == 0 ) {
                                strcpy(conf->dlAuthUrl, strrchr(temp, '^')+1);
                                snprintf(varBuff, sizeof(varBuff), conf->dlAuthUrl, "mail@jjeong.com");
                                printf("DlAuthUrl : %s\n", varBuff);
                                memset(varBuff, 0, 256);

                        }

                        if ( strncasecmp(temp, "DlAuthCompareStr", strlen("DlAuthCompareStr")) == 0 ) {
                                strcpy(conf->dlAuthCompareStr, strrchr(temp, '^')+1);

                                if ( strstr("SUCCESS", conf->dlAuthCompareStr) ) {
                                        printf("DlAuthCompareStr SUCCESS\n");
                                }
                                printf("DlAuthCompareStr : %s\n", conf->dlAuthCompareStr);
                        }

                        if ( strncasecmp(temp, "AhfServer", strlen("AhfServer")) == 0 ) {
                                strcpy(conf->ahfServer, strrchr(temp, '^')+1);
                                printf("AhfServer : %s\n", conf->ahfServer);
                        }

                        if ( strncasecmp(temp, "AhfPort", strlen("AhfPort")) == 0 ) {
                                conf->ahfPort = atoi(strrchr(temp, '^')+1);
                                printf("AhfPort : %d\n", conf->ahfPort);
                        }

                        if ( strncasecmp(temp, "AhfUser", strlen("AhfUser")) == 0 ) {
                                strcpy(conf->ahfUser, strrchr(temp, '^')+1);
                                printf("AhfUser : %s\n", conf->ahfUser);
                        }

                        if ( strncasecmp(temp, "AhfPass", strlen("AhfPass")) == 0 ) {
                                strcpy(conf->ahfPass, strrchr(temp, '^')+1);
                                printf("AhfPass : %s\n", conf->ahfPass);
                        }

                        if ( strncasecmp(temp, "AhfDb", strlen("AhfDb")) == 0 ) {
                                strcpy(conf->ahfDb, strrchr(temp, '^')+1);
                                printf("AhfDb : %s\n", conf->ahfDb);
                        }

                        if ( strncasecmp(temp, "AhfQuery", strlen("AhfQuery")) == 0 ) {
                                strcpy(conf->ahfQuery, strrchr(temp, '^')+1);
                                snprintf(varBuff, sizeof(varBuff), conf->ahfQuery, "TEST");
                                printf("AhfQuery: %s\n", varBuff);
                                memset(varBuff, 0, 256);
                        }

                        if ( strncasecmp(temp, "SkipDomain", strlen("SkipDomain")) == 0 ) {
                                strcpy(conf->skipDomain, strrchr(temp, '^')+1);
                                printf("SkpDomain : %s\n", conf->skipDomain);
                        }

                }
        } else {
        }

        fclose(fp);

        return 1;
}


int main(int argc, char *argv[]) {
        CONFIG conf;

        printf("file full path : %s\n", argv[1]);

        setConfig(&conf, argv[1]);

        return 1;
}

일부 코드는 레퍼런스 코드 가져다 사용하였습니다.

뭐 이런 종류의 코드는 구글링 하면 많이 나오니까.. ^^;;

tags : c, config, Property
Trackbacks 0 : Comments 0

Write a comment