Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Spring Cloud micro-service public configuration processing

2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/03 Report--

Spring Cloud Config Server provides the function of micro-service to obtain configuration. These configuration files (application.yml or application.properties) are usually maintained in git or database, and support dynamic refresh through RefreshScope, which is relatively flexible to use. However, as there are more and more microservices, the following problems will be encountered:

The sensitive number of configuration files, such as database address and account information, is presented in each profile and needs to be modified one by one. There are many redundant configurations in each micro-service profile (such as Eureka,Feign). Once these parts are adjusted, they need to be adjusted for each micro-service, which greatly increases the pressure on operation and maintenance.

To solve the above problems, we can start with the configServer service, as shown below:

Different service ABC, no matter how many files are configured in the configuration center repository, must be the configuration of the final application of the service returned from the ConfigServer. Get the configuration, usually by calling an address of ConfigServer, such as:

Http://localhost:8021/common_rent/dev/aliyun_dev

Common_rent is application name,dev. Profile,aliyun_dev is label (a branch of git). The processing interface of this address is the EnvironmentController of ConfigServer, so the above purpose can be achieved by intercepting this interface, extracting sensitive information or public configuration to the application.yml of configServer, and replacing or stitching before returning.

Code example:

Interceptor implementation

@ Component@Aspectpublic class ResourceLoaderInterceptor {private static Log logger = LogFactory.getLog (ResourceLoaderInterceptor.class); @ ResourceExternalProperties externalProperties;@Around ("execution (* org.springframework.cloud.config.server..*Controller.* (..)") public Object commonPropertiesResolve (ProceedingJoinPoint joinPoint) throws Throwable {Object returnObj = null; Object [] args = joinPoint.getArgs (); StopWatch stopWatch = new StopWatch (); try {stopWatch.start (); returnObj = joinPoint.proceed (args) If (Environment.class.isInstance (returnObj)) {Environment environment = (Environment) returnObj; if (environment.getPropertySources ()! = null & & environment.getPropertySources (). Size () > 0) {for (PropertySource propertySource: environment.getPropertySources ()) {placeHolderResolve ((Map) propertySource.getSource ()) } catch (Throwable throwable) {logger.error (ExceptionUtils.getStackTrace (throwable));} finally {stopWatch.stop (); System.out.println (stopWatch.getTotalTimeMillis ());} return returnObj;} private void placeHolderResolve (Map source) {Map placeHolders = collectConfigSet () For (String key: source.keySet ()) {Object value = source.get (key); Object valueAfterReplace = null; if (value! = null) {if (String.class.isInstance (value) & & ((String) value) .requests ("${ext.") {String varExp = (String) value For (String variable: placeHolders.keySet ()) {String vk = "${" + variable + "}"; if (varExp.contains (vk)) {Object replaceValue = placeHolders.get (variable) If (replaceValue! = null) {if (varExp.equalsIgnoreCase (vk)) {valueAfterReplace = replaceValue; break } else {varExp = StringUtils.replace (varExp, vk, "" + replaceValue); if (! varExp.contains ("${")) {break } else {logger.error ("Property" + vk + "is not properly configured!") } if (valueAfterReplace! = null) {source.put (key, valueAfterReplace);} else if (varExp.contains ("${")) {logger.error ("Property" + varExp + "is not properly configured!") } else {source.put (key, varExp);} private Map collectConfigSet () {Map placeHolders = new HashMap (); Field [] fields = ExternalProperties.class.getDeclaredFields (); for (int I = 0; I < fields.length; iTunes +) {try {Field propertiesField = fields [I] ResourcePrefix resourcePrefix = propertiesField.getAnnotation (ResourcePrefix.class); String prefix = resourcePrefix.value (); ExtDataSource extDataSource = (ExtDataSource) BeanUtils.getPropertyDescriptor (ExternalProperties.class, propertiesField.getName ()). GetReadMethod (). Invoke (externalProperties); if (extDataSource! = null) {Field [] fields2 = ExtDataSource.class.getDeclaredFields () For (Field datasourceField: fields2) {try {ResourcePrefix annotation = datasourceField.getAnnotation (ResourcePrefix.class); String suffix = annotation.value (); Object sourceFieldValue = BeanUtils.getPropertyDescriptor (ExtDataSource.class, datasourceField.getName ()) .getReadMethod () .invoke (extDataSource) If (sourceFieldValue! = null) {placeHolders.put (prefix + "." + suffix, sourceFieldValue);} catch (Exception e) {logger.error (ExceptionUtils.getStackTrace (e)) } catch (Exception e) {logger.error (ExceptionUtils.getStackTrace (e));}} return placeHolders;}} ExternalProperites implements @ ConfigurationProperties (prefix = "external", ignoreUnknownFields = true) public class ExternalProperties implements Serializable {@ ResourcePrefix (value = "ext.spring.datasource") private ExtDataSource datasource @ ResourcePrefix (value = "ext.spring.data.mongodb") private ExtDataSource mongodb; @ ResourcePrefix (value = "ext.spring.redis") private ExtDataSource redis; @ ResourcePrefix (value = "ext.spring.rabbitmq") private ExtDataSource rabbitmq; public ExtDataSource getDatasource () {return datasource;} public void setDatasource (ExtDataSource datasource) {this.datasource = datasource;} public ExtDataSource getRabbitmq () {return rabbitmq } public void setRabbitmq (ExtDataSource rabbitmq) {this.rabbitmq = rabbitmq;} public ExtDataSource getMongodb () {return mongodb;} public void setMongodb (ExtDataSource mongodb) {this.mongodb = mongodb;} public ExtDataSource getRedis () {return redis;} public void setRedis (ExtDataSource redis) {this.redis = redis;}}

ExtDataSource implementation

Public class ExtDataSource {@ ResourcePrefix (value = "host") private String host;@ResourcePrefix (value = "port") private Integer port;@ResourcePrefix (value = "url") private String url;@ResourcePrefix (value = "uri") private String uri;@ResourcePrefix (value = "username") private String userName;@ResourcePrefix (value = "password") private String password;public String getUrl () {return url;} public void setUrl (String url) {this.url = url;} public String getHost () {return host } public void setHost (String host) {this.host = host;} public Integer getPort () {return port;} public void setPort (Integer port) {this.port = port;} public String getUri () {return uri;} public void setUri (String uri) {this.uri = uri;} public String getUserName () {return userName;} public void setUserName (String userName) {this.userName = userName;} public String getPassword () {return password } public void setPassword (String password) {this.password = password;}} ResourcePrefix implementation @ Target ({ElementType.FIELD, ElementType.TYPE}) @ Retention (RetentionPolicy.RUNTIME) public @ interface ResourcePrefix {String value ();}

Then add relevant information to the application.yml of configServer, such as

External: datasource: host: 122.122.111.111 port: 3307 userName: usr password: pwd mongodb: host: 122.122.111.111 port: 20467 uri: 122.122.111.111:20467122.122.111.112:20467122.122.111.112:20467 userName: usr password: pwd redis: uri: 122.122.111.113:6379122.122.112.113:6379122.122.111.113:6379 password: redispassword rabbitmq: Host: 122.122.111.113 port: 20467 userName: usr password: pwd

Replace the database-related information in ServiceA's configuration file serviceA_dev.yml with variables, taking mysql as an example

Spring.datasource.uri: url: jdbc:mysql://# {ext.spring.datasource.host}: # {ext.spring.datasource.port} / dbName?useUnicode=true&characterEncoding=utf8

ServiceB and serviceC configuration files can be replaced at one time by doing the same treatment.

Later, if you need to add public configuration, you can add it directly in the middle of the configuration of ConfigServer and adjust the implementation logic of the interceptor.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report