SpringCloud Config etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster
SpringCloud Config etiketine sahip kayıtlar gösteriliyor. Tüm kayıtları göster

27 Eylül 2021 Pazartesi

SpringCloud Config @RefreshScope Anotasyonu

Giriş
Şu satırı dahil ederiz
import org.springframework.cloud.context.config.annotation.RefreshScope;
@RefreshScope anotasyonunu açıklaması şöyle
When this annotation is applied to a Spring component (i.e., a @Component, @Service, @RestController, etc.), the component is re-created when a configuration refresh occurs, in this case giving an updated value for ${hello.message}.

You can refresh an application’s configuration by including the Spring Boot Actuator dependency, exposing the /actuator/refresh endpoint, and sending an empty POST request
Don’t use @RefreshScope in controllers
Açıklaması şöyle
Now, what about using @RefreshScope in controllers? While it's technically possible to use @RefreshScope in controllers, it's generally not recommended. Controllers are typically responsible for handling incoming requests and generating responses, and their behavior shouldn't be affected by changes to configuration settings. In addition, refreshing a controller could result in requests being dropped or delayed, which could have a negative impact on the user experience.

Instead, it’s better to use @RefreshScope with beans that are responsible for handling configuration settings, such as @ConfigurationProperties or @Value beans. By using @RefreshScope with these beans, you can ensure that changes to the configuration are applied across the entire application without having to restart it.
Örnek 
Şöyle yaparız. Burada Config Server'dan okunacak değer @Vaue ile çekiliyor.
@RefreshScope
@RestController
@RequestMapping("/secure")
public static class SecureController {
  @Value("${hello.message}")
  private String helloMessage;
  
  @GetMapping
  public String secure(Principal principal) {
    return helloMessage;
  }
}
Örnek
Şöyle yaparız. Burada @RefreshScope ile yeni konfigürasyonun okunabileceği belirtiliyor. Konfigürasyon verisi sürekli env.getProperty() şeklinde alınıyor.
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;

@RefreshScope
@RestController
public class HelloController {
  @Autowired
  private Environment env;
  
  @GetMapping("/hello")
  public ResponseEntity<String> getHello(Model model) {   
    return new ResponseEntity<String>( env.getProperty("message"), HttpStatus.OK);
  }
}
Eğer Config Server'da bir şey değişirse Client uygulamayı ayarları tekrar okuması için  tetiklemek gerekir. Şöyle yaparız
http://localhost:8080/actuator/refresh


23 Ağustos 2021 Pazartesi

SpringCloud Config Server Kullanımı

Giriş
Açıklaması şöyle
With the Spring Cloud Configuration server, we can place the configuration files for all our microservices in a central configuration repository that will make it much easier to handle them. Our microservices will be updated to retrieve their configuration from the configuration server at startup.
Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-config-server</artifactId>
</dependency>
JDBC için şu satırı dahil ederiz
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jdbc</artifactId>
  </dependency>
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
Config Repository Olarak Ne Kullanılabilir
Açıklaması şöyle. Yani repository olarak bir sürü seçenek var
The config server supports the storing of configuration files in a number of different backends, for example:  

Git repository  
Local filesystem  
HashiCorp Vault  
A JDBC database  

Other Spring projects have added extra backends for storing configuration, for example, the Spring Cloud AWS project, which has support for using either AWS Parameter Store or AWS Secrets Manager as backends. 
Vault için bir örnek burada

Deciding on the Initial Client Connection  
Açıklaması şöyle
By default, a client connects first to the config server to retrieve its configuration....
It is also possible to do this the other way around, that is, the client first connecting to the discovery server to find a config server instance and then connecting to the config server to get its configuration. There are pros and cons to both approaches.  

Note: One concern with connecting to the config server first is that the config server can become a single point of failure. If the clients connect first to a discovery server, such as Netflix Eureka, there can be multiple config server instances registered so that a single point of failure can be avoided.
Config Server API
Açıklaması şöyle
The config server exposes a REST API that can be used by its clients to retrieve their configuration. In this chapter, we will use the following endpoints in the API:  

1. /actuator: The standard actuator endpoint is exposed by all microservices. 
As always, these should be used with care. They are very useful during development but must be locked down before being used in production.  

2. /encrypt and /decrypt: Endpoints for encrypting and decrypting sensitive information. These must also be locked down before being used in production.  

3. /{microservice}/{profile}: Returns the configuration for the specified microservice and the specified Spring profile.
actuator/refresh microservice'leri yeni konfigürasyondan haberdar etmek için kullanılır. Şeklen şöyle


/encrypt ve /decrypt
Örnek - symmetric
Şöyle yaparız
server.port = 8888

# Set path to Local Git Repository
spring.cloud.config.server.git.uri = /home/...

# Setting the key for Symmetric Encryption and Decryption
encrypt.key = secret
Böylece artık 
localhost:888/encrypt
adresine POST yaparsak gönderdiğimiz veriyi şifreli olarak gelir alırız. Eğer şifreli veriyi açmak istersek
localhost:888/encrypt
adresine yine POST yapmak gerekir.
Örnek - asymmetric
keytool komutu ile bir public/private key JKS oluşturulur. Şöyle yaparız
keytool -genkeypair \
  -keyalg RSA \
  -dname "cn=Config-Serv, ou=Java, o=Spring, c=US" \
  -alias configserv \
  -keypass nopass \
  -keystore simple.jks \
  -storepass nopass
Şöyle yaparız
# Path of Key-Pairs to be used. (Recommended: Use Classpath)
encrypt.keyStore.location = claspath:/simple.jks

# Represents the password to read jks file (keypass)
encrypt.keyStore.password = nopass

# Represents the password to read jks file (storepass)
# From Java-11 keystore password and secret should be same.
# Optional to specify. When not given keystore password is used as secret by default.
encrypt.keyStore.secret = nopass

# Value of Alias used in jks generation
encrypt.keyStore.alias = configserv

# Format of keystore (Default: jks)
encrypt.keyStore.type = jks
Kullanım
1. @EnableConfigServer anotasyonu tanımlanır

2. Sunucu için SpringCloud Config Server application.properties ayarları tanımlanır

3. İstemci için ayarlar yapılır. Ayarlarda application + profile + label bilgilerinin belirtilmesi gerekiyor. Yani şöyledir
application-name
|--- application-name-dev.properties
|--- application-name-qa.properties














1 Şubat 2021 Pazartesi

SpringCloud Config Server Sunucu İçin application.properties Ayarları

Giriş
Tüm ayarlar
spring.cloud.config.server.XXX ile belli oluyor.
XXX yerine 
- jdbc
- native
- git

kullanılabilir

Konfigürasyon Dosya İsimleri
Konfigürasyon Dosya İsimleri belli bir formatta olmalı. Açıklaması şöyle
Let’s take a moment to discuss the naming convention for the configuration files. The filenames are important and must be in a certain pattern for your microservices to pick them up:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

Where:

- {application} is the name of your microservice specified via your microservice’s spring.application.name property. In this case, service-one and service-two.
- {profile} matches the list of profiles your microservice is running via the spring.profiles.active property. In this case, profile1 and profile2.
- {label} is an additional descriptor usually corresponding to a version control branch, e.g. dev or stg. It can be manually set via the spring.cloud.config.label property in the microservice’s bootstrap.properties file or set on the command line (-Dspring.cloud.config.label).
Açıklaması şöyle. Yani "neo4j-client.yaml" dosyasına erişmek için "localhost:8888/neo4j-client/default" adresine erişmek gerekir. Burada profile verilmediği için default ismine sahip dosyaya erişilir.
Many tutorials use the /{application}/{profile} notation. The /{application} piece references the name you give your client application. This is an arbitrary name, except that your config file (in our case, yaml) needs to have the same name. Config file naming follows the pattern {application}-{profile}. If you do not specify a -{profile} (e.g., development, production) on the config file name, it uses the default profile.
Örnek - github
Eğer sunucu 8888 adresinde çalışıyorsa, config-client uygulamasını taklit etmek için şöyle yaparız. Burada profile değeri development, label değeri ise main
curl http://localhost:8888/config-client/development/main
Neden label olarak main verildiğinin açıklaması şöyle
You must provide the branch name if you are using the URL with the label as if not provided it will take default as master( as it defaulted in GitHub), however, GitHub has changed it to main, so you need to provide main in the path

Örnek - JDBC
Şöyle yaparız
spring.cloud.config.server.jdbc.sql= SELECT PROP_KEY, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?
spring.cloud.config.server.jdbc.order=1
Veri tabanı tablosu şöyledir
create table properties(
  id integer not null auto_increment,
  CREATED_ON datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  APPLICATION varchar(255),
  PROFILE varchar(255),
  LABEL varchar(255),
  PROP_KEY varchar(255),
  VALUE varchar(255), 
primary key (id)
);

INSERT INTO properties (APPLICATION, PROFILE, LABEL, PROP_KEY, VALUE) VALUES
('spring-cloud-config-client', 'dev', 'latest', 'URL_A', 'https://client-urlA-dev.com'),
('spring-cloud-config-client', 'dev', 'latest', 'URL_B', 'https://client-urlB-dev.com'),
('spring-cloud-config-client', 'test', 'latest', 'URL_A', 'https://client-urlA-test.com'),
('spring-cloud-config-client2','dev', 'latest', 'URL_A', 'https://client2-urlA-dev.com'),
('spring-cloud-config-client2','test', 'latest', 'URL_A', 'https://client2-urlA-t.com');
Ulaşmak için şöyle yaparız
http://<server port-no>/<APPLICATION>/<PROFILE>/<LABEL> 
http://localhost:8888/spring-cloud-config-client/dev/latest

Örnek - Dosya Sistemi
Şöyle yaparız
server.port=8888
spring.cloud.config.server.native.search-locations=/path/to/config/folder
spring.security.user.name=configUser
spring.security.user.password=configPass
Örnek - Docker
Şöyle yaparız
server.port: 8888 
 
spring.cloud.config.server.native.searchLocations: file:${PWD}/config-repo 
 
management.endpoint.health.show-details: "ALWAYS" 
management.endpoints.web.exposure.include: "*" 
 
logging.level.root: info  
 
--- 
spring.config.activate.on-profile: docker 
spring.cloud.config.server.native.searchLocations: file:/config-repo  
Örnek - git Dosya Sistemi
Açıklaması şöyle
It's standard practice to run a configuration server at port 8888. For a Windows environment, kindly keep an additional "/". For other environments, "//" will work. spring.cloud.config.server.git.uri=file://d:/config-properties
Şöyle yaparız
spring.application.name=hello-config-server
server.port=8888
spring.cloud.config.server.git.uri=file:///d:/config-properties
Dosyaları git'e eklemek için şöyle yaparız
git init .

creat foo.properties

git add foo.properties
git commit -m 'very first configuration'
Örnek - git Sunucusu
Şöyle yaparız
spring.cloud.config.server.git.uri=https://github.com/abcd/springboot
spring.cloud.config.server.git.uri.username=test
spring.cloud.config.server.git.uri.password=test
Örnek
Şöyle yaparız. Burada git repository clone'lanıyor
server: port: 8888 spring: cloud: config: server: git: uri: https://github.com/NavaliaHQ/api-config.git searchPaths: - '{application}' username: GIT_USER #update with github username password: GIT_PASSWORD #update with github password clone-on-start: true default-label: master


4 Ocak 2021 Pazartesi

SpringCloud Config Client

Giriş
Config Server için @EnableConfigServer yazısına bakınız.
Konfigürasyon değiştirilince tekrar okumak için @RefreshScope yazısına bakınız.

Microservice yazılımı konfigürasyon ayalarını artık Config Server'dan çekecektir

Maven
Şu satırı dahil ederiz
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-config</artifactId>
</dependency>
bootstrap.yml or bootstrap.properties Nedir
Açıklaması şöyle. İstemci tarafında kullanılır. Artık bu dosyaya gerek yok
bootstrap.yml is loaded before application.yml.

It is typically used for the following:

- when using Spring Cloud Config Server, you should specify spring.application.name and spring.cloud.config.server.git.uri inside bootstrap.yml
- some encryption/decryption information
Örnek - Eski Kullanım
Açıklaması şöyle
If you are using the latest version of spring boot use spring.config.import=... instead of spring.cloud.config.uri=...
Şöyle yaparız. Burada github'daki latest branch'ine atıfta bulunuluyor
spring.cloud.config.uri=http://localhost:8888
spring.application.name=spring-cloud-config-client
spring.cloud.config.label=latest
spring.profiles.active=dev
Örnek
Şöyle yaparız. Burada github'daki main branch'ine atıfta bulunuluyor
spring.application.name=config-client 
spring.profiles.active=development
spring.cloud.config.uri=http://localhost:8888
spring.cloud.config.label=main
Örnek - Yeni Kullanım
Şöyle yaparız.
spring.config.import=optional:configserver:http://localhost:8888 # Config sunucu adresi
spring.application.name=batch-jobs # Dosya ismi
spring.profiles.active=dev # Profile ismi
Örnek - Yeni Kullanım
Şöyle yaparız
server.port=8083

spring.application.name=neo4j-client # Dosya ismi
spring.config.import=configserver:http://localhost:8888/ # Config sunucu adresi
Örnek - Yeni Kullanım Yaml Olarak
Şöyle yaparız
spring:
  application:
    name: spring-boot-starter
  profiles:
    active: dev
  config:
    import: optional:configserver:http://localhost:8888

management:
  endpoints:
    web:
      exposure:
        include: "*"
Örnek - Retry Ayarları
Şöyle yaparız. spring.cloud.config.uri ile Config Server'ın adresi belirtilir.
spring.application.name=hello-service
server.port=8080
spring.profiles.active=development
spring.cloud.config.uri=http://localhost:8888
Eğer Config Server ulaşılamıyorsa, şu ayarlar kullanılabilir
spring.cloud.config.fail-fast
spring.cloud.config.retry.initial-interval
spring.cloud.config.retry.multiplier
spring.cloud.config.retry.max-interval
spring.cloud.config.retry.max-attempts
spring.application.name Alanı
Okunacak property dosyasını ismini belirtir. Dosya ismine aktif profile da eklenir. Açıklaması şöyle
This is the identifier for the microservice application and there will be a property file with the same name in the repository. This will identify which property file to fetch from the repository for a particular microservice. For example, for hello-service.properties, we would use hello-service-development.properties (the -development suffix tells the system to fetch code for development profile).
Örnek - Çift Spring Security Ayarı
Eğer zaten Spring Security varsa, /actuator/refresh adresini farklı bir şifre ile korumak isteyebiliriz. Şöyle yaparız. Burada @Order(1) ile actuator/refresh adresine öncelik veriliyor.
@Order(1)
@Configuration
public static class ActuatorSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity http) throws Exception {
    http
      .csrf().disable()
      .antMatcher("/actuator/*")
      .authorizeRequests()
        .antMatchers("/actuator/*").authenticated()
      .and()
        .httpBasic();
  }
  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
      .withUser("serviceOneUser")
      .password("{noop}serviceOnePassword")
      .roles("USER");
  }
}

@Order(2)
@Configuration
public static class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  public void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .anyRequest().authenticated()
      .and()
       .oauth2Login();
  }
}
Bu adresi şifreyle tetiklemek için şöyle yaparız
curl -u serviceOneUser:serviceOnePassword -X POST http://localhost:8001/actuator/refresh
Örnek
Şöyle yaparız. Burada Config Server'dan okunacak değer @Vaue ile çekiliyor.
import org.springframework.cloud.context.config.annotation.RefreshScope;
...
@RefreshScope
@RestController
@RequestMapping("/secure")
public static class SecureController {
  @Value("${hello.message}")
  private String helloMessage;
  
  @GetMapping
  public String secure(Principal principal) {
    return helloMessage;
  }
}

21 Mayıs 2019 Salı

SpringCloud Config Server @EnableConfigServer

Giriş
Şu satırı dahil ederiz
import org.springframework.cloud.config.server.EnableConfigServer;
Açıklaması şöyle
@EnableConfigServer is class-level annotation. It helps Spring Cloud Config Server to be embedded in Spring Boot application very easily and the @EnableConfigServer annotation makes the Spring Boot application act as a Configuration Server.
Konfigürasyon verisinin Repository 'den çekilerek kullanılmasını sağlar. Repository olarak Git, SVN, Dosya Sistemi kullanılabilir

Ayarları okuyan taraf için SpringCloud Config Client yazısına bakınız.

Örnek - git
Örneği buradan aldım
1. Bir tane dizin yarat, örneğin ismi  "config-properties" olsun
2. Bu dizinde bir tane properties dosyası yarat, örneğin ismi "hello-service.properties" olsun. Her dosya bir servise ait. Burada servisin ismi "hello-service". Dosyanın içi şöyle olsun
message=Hello world - this message is from config server
3. application.properties dosyasında git ile saklanan repository yolunu belirtmek gerekir. 

4. Konfigürasyon Sunucusu Uygulaması
@EnableConfigServer anotasyonu "spring.cloud.config.server.git.uri" ile belirtilen yoldaki her properties dosyası için bir tane Rest Endpoint oluşturur. 

Örnek
Şöyle yaparız
@EnableConfigServer
@SpringBootApplication
public class HelloConfigServerApplication {
  public static void main(String[] args) {
    SpringApplication.run(HelloConfigServerApplication.class, args);
  }
}
Sunucu çalıştıktan sonra hello-service.properties dosyasına erişmek için şöyle yaparız. Burada default kelimesi hello-service.properties anlamına geliyor.
http://localhost:8888/hello-service/default
Çıktı olarak şunu alırız
{
  "name": "hello-service",
  "profiles": [
    "default"
  ],
  "label": null,
  "version": "3da88aa3c6103cc7f2b383a3ee5d5dad5e6e870c",
  "state": null,
  "propertySources": [
    {
      "name": "file:///d:/config-properties/hello-service.properties",
      "source": {
        "message": "Hello world - this message is from config server"
      }
    }
  ]
}
Eğer bu servise ait hello-service-development.properties dosyasına erişmek istersek şöyle yaparız
http://localhost:8888/hello-service/development