springcloud config 分布式配置中心

一、介绍

1、场景:

微服务系统中,系统多、实例多,如果每个系统都有自己一套配置加载、维护的机制,会导致在生产过程中因为配置问题引发的不必要的沟通成本、故障风险。需要采用分布式配置中心统一管理、统一实现方式。

2、Spring cloud config特性

服务端:存储方式(git、svn、本地文件)、配置读取方式(环境化、多项目仓库)、安全性(访问密码、加密存储)、自动刷新。
客户端:加载远程配置、刷新配置、@refreshscope作用域刷新、集成消息总线。

二、docker中运行gitlab、rabbitmq的方式

1、下载安装: docker toolbox
windows下载:https://www.docker.com/products/docker-toolbox
下载后控制台执行命令:docker-machine create –engine-registry-mirror=”https://s0iielsh.mirror.aliyuncs.com” –engine-insecure-registry=”0.0.0.0/0” -d virtualbox default
这时可能提示没有boot2docker镜像,这样默认就会通过git下载,但是速度实在受不了,根本跑不动,但是可以直接通过安装的docker文件夹中找到

直接复制到C:\Users\Administrator.docker\machine\cache

2、 查看虚拟机IP等信息:docker-machine env default
注:如果想直接在windows命令窗口内使用docker命令,将上一条命令输出的内容,复制粘贴到控制台执行一次即可
3、 创建docker中的网络
docker network create dongnao_net

4、 运行gitlab
docker run -d –net=dongnao_net –publish 1443:443 –publish 18080:80 –name gitlab –restart always gitlab/gitlab-ce:latest
端口18080,通过你的虚拟机IP取访问就可以看到页面了

5、 运行rabbitmq
docker run -d –net=dongnao_net –name rabbitmq –publish 5671:5671 –publish 5672:5672 –publish 4369:4369 –publish 25672:25672 –publish 15671:15671 –publish 15672:15672 rabbitmq:management
连接的端口是 5672
web控制台是 15672
6、说明
Oracle VM VirtualBox是一个管理虚拟机的工具
Docker Quickstart Terminal是用于连接操作虚拟机的

由于虚拟机经常启动失败,我遇到失败的原因经常是vboxdrv服务没有安装或没有成功启动;
解决办法:开始后第一件事就尝试打开虚拟机,如果不成功就找到安装目录下的vboxdrv文件夹,
如C:\Program Files\Oracle\VirtualBox\drivers\vboxdrv,右击VBoxDrv.inf,选安装,然后重启电脑。
再在virturalBox里启动虚拟机,然后打开docker,运行命令 docker start rabbitmq来启动rabbitmq,服务器启动就正常了,这时也可以在浏览器上访问rabbitmq和gitlab了。

三、注册中心eureka

说明:以下代码注释说明得非常清楚,就不多做解释,有疑问的欢迎留言提问!
1、pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- spring boot 封装spring
         starter封装、自动配置autoconfiguration
     -->
    <parent>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-parent</artifactId>
        <version>Dalston.SR1</version>
        <relativePath />
    </parent>
    <groupId>com.dongnaoedu.springcloud</groupId>
    <artifactId>lession-2-eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- spring-boot-starter-web web项目,集成容器tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spring-boot-starter-actuator 管理工具/web 查看堆栈,动态刷新配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- cloud eureka组件 注册中心 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2、application.yml:

# 上下文初始化加载
info:
  name: Eureka server
  contact: 动脑科技VIP

spring:
  profiles:
    active: dev
---
spring:
  profiles: dev
server:
  port: 8761
eureka:
  client:
    # 是否注册到eurekaserver
    registerWithEureka: true
    # 是否拉取信息
    fetchRegistry: false
    # eureka server地址
    serviceUrl:
      defaultZone: http://127.0.0.1:8761/eureka/
  server:
    waitTimeInMsWhenSyncEmpty: 0
    # false 关闭自我保护,不管如何都要剔除心跳检测异常的服务
    enableSelfPreservation: true
  instance:
    hostname: eureka1

3、bootstrap.yml

# 比application context先加载
# 应用名称
spring:
  application:
    name: eureka-server

4、启动类

package com.dongnaoedu.springcloud;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
    public static void main(String[] args) {
        new SpringApplicationBuilder(EurekaApp.class).web(true).run(args);
    }
}

四、server

1、application.yml:

info:
  name: 配置中心
  contact: 动脑VIP

server:
  port: 8888
# 使得/refresh不需要验权
management:
  security:
    enabled: false
# 访问时需要提供用户和密码
security:
  # 这个接口不做用户名密码校验, /monitor接收git刷新通知
  ignored: /monitor
  user:
    name: user
    password: 12345678
encrypt:
  # 加解密用的秘钥
  key: 12345678

# rabbitmq的地址 用户名 密码
spring:
  rabbitmq:
    host: 192.168.99.100
    username: guest
    password: guest
  profiles:
    active: dev

# 不同环境的配置
---
spring:
  profiles: dev
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://127.0.0.1:8761/eureka/
  instance:
    preferIpAddress: true
---
spring:
  profiles: prod
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://eureka1:8761/eureka/,http://eureka2:8762/eureka/,http://eureka3:8763/eureka/
  instance:
    preferIpAddress: true

2、bootstrap.yml:

spring:
  application:
    # 配置文件就是用这个来做文件名的,要对应的哦。
    name: lession-2-config-server
  profiles:
    active: dev,git
  cloud:
    config:
      server:
        # 本地文件
        native:
          # 用本地文件夹存储配置,仅作配置示例,没起作用。要想起作用,将上面的 active中git 改为 native
          searchLocations: file:D:\\cloud\\dongnao\\configrepo
        # git仓库 gitlab地址
        git:
          # 记得在先gitlab上创建一个对应的project
          uri: http://192.168.99.100:18080/root/project1.git
          search-paths: /
          username: root
          password: 12345678
          repos:
            # 不同环境不同的库,这里的话,只有当应用中的spring.profiles.active=staging的时候才生效
            lession-2-sms-sys-staging:
              pattern: '*/staging'
              # 记得在先gitlab上创建一个对应的project
              uri: http://192.168.99.100:18080/root/lession-2-config-repo-staging.git
            # 不同项目不同库
            lession-2-sms-webmvc:
              pattern:
                # 这里是根据服务名称匹配的spring.application.name
                - lession-2-sms-webmvc/**
                - lession-2-sms-webmvc*
              # 这里面的是本地git仓库的,不知道配置本地git仓库的也可以像上面一样配置成远程git地址
              uri: file:D:\cloud\dongnao\config-repo
        # 加解密
        encrypt:
          enabled: true
# svn环境
# spring.profiles.active=subversion
# spring.cloud.config.server.svn.uri=http:#127.0.0.1:1234/sms-sys/development/trunk
# spring.cloud.config.server.svn.username=xxx
# spring.cloud.config.server.svn.password=xxx

3、启动类

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class ConfigServerApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(ConfigServerApplication.class).web(true).run(args);
    }
}

4、pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- spring boot 封装spring
         starter封装、自动配置autoconfiguration
     -->
    <parent>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-parent</artifactId>
        <version>Dalston.SR1</version>
        <relativePath />
    </parent>
    <groupId>com.dongnaoedu.springcloud</groupId>
    <artifactId>lession-2-config-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- spring-boot-starter-web web项目,集成容器tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spring-boot-starter-actuator 管理工具/web 查看堆栈,动态刷新配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <!-- spring-boot-starter-security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <!-- cloud config组件 配置中心 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-monitor</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

五、客户端

1、pom文件

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- spring boot 封装spring
         starter封装、自动配置autoconfiguration
     -->
    <parent>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-parent</artifactId>
        <version>Dalston.SR1</version>
        <relativePath />
    </parent>
    <groupId>com.tony</groupId>
    <artifactId>lession-2-sms-sys</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Dalston.SR1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <!-- spring-boot-starter-web web项目,集成容器tomcat -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- spring-boot-starter-actuator 管理工具/web 查看堆栈,动态刷新配置 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!-- spring bus 事件通知实现自动刷新 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2、application.yml

# eureka是必须的

spring:
  profiles:
    # 这里的意思是启用dev环境
    active: dev

---
spring:
  profiles: dev
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      defaultZone: http://127.0.0.1:8761/eureka
  instance:
    preferIpAddress: true

---
spring:
  profiles: prod
eureka:
  client:
    registerWithEureka: true
    fetchRegistry: true
    serviceUrl:
      # 这里写成eureka1,是因为我修改系统的hosts, 127.0.0.1 eureka1
      defaultZone: http://eureka1:8761/eureka
  instance:
    preferIpAddress: true

3、bootst.yml

spring:
  application:
    name: lession-2-sms-sys
  cloud:
    config:
      discovery:
        # 使用eureka发现配置中心服务
        enabled: true
        # 配置中心服务名称/ID
        serviceId: lession-2-config-server
      # 登录用户名和密码
      username: user
      password: 12345678
      # 覆盖本地配置
      overrideNone: false
      failFast: true
      name: ${spring.application.name}
      profile: ${spring.profiles.active}
      # git仓库中,可以使用label来做不同版本的配置管理,默认是master,可以用来做版本管理。比如“2.0”
      label: 'master'

4、启动类

package com.dongnaoedu.springcloud.service;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication
@ComponentScan("com.dongnaoedu")
@EnableEurekaClient
public class SmsServiceApplication {
    public static void main(String[] args) {
        new SpringApplicationBuilder(SmsServiceApplication.class).web(true).run(args);
    }
}

5、controller

package com.dongnaoedu.springcloud.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RefreshScope // 此处很重要 +++
public class SmsController {

    @Value("${tony.configString}")
    private String configString;

    // 测试注入tony.configString配置
    @RequestMapping("/test")
    public String sendSms() {
        return "configString的值:" + configString;
    }

    @Autowired
    Environment env;

    @RequestMapping("/get/{configName}")
    public String test(@PathVariable String configName) {
        return configName + "的值为:" + env.getProperty("tony." + configName);
    }
}

6、redis

package com.dongnaoedu.springcloud.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import redis.clients.jedis.JedisPool;

@Configuration
@RestController
@RequestMapping("/redis")
public class RedisController {
    @Autowired
    Environment env;

    @Bean
    @RefreshScope// 在refresh之后,这个实例会被刷新
    public JedisPool jedisPool() {
        String host = env.getProperty("redis.host");
        int port = env.getProperty("redis.port", Integer.class);
        return new JedisPool(host, port);
    }

    @Autowired
    private JedisPool jedisPool;

    // 获取一个key的值 并打印出来
    @RequestMapping("/get/{key}")
    public String sendSms(@PathVariable String key) {
        String value = jedisPool.getResource().get(key);
        return "    redis中" + key + "的值为:" + value;
    }
}

当gitlab上的配置改变了,直接调用接口获取到的值会是改变之前的值,得先调用refresh(post接口)接口刷新后再调用目标接口,这样才能获取到最新的值。

六、MVC

1、springmvc中的配置加载 和 环境化
profile激活不同环境,加载不同的配置
普通mvc程序通过 xml中 <beans profile="dev">...</beans> 方式可以进行配置

  <beans profile="test">
    <bean id="testDatasource" class="xxxxx.datasource"/>
  </beans>
    <beans profile="prod">
    <bean id="prodDatasource" class="xxxxx.datasource"/>
    </beans>  

2、在xml配置文件中配置<context:property-placeholder location="classpath:sms.properties"/>就可以设置${}里取到的变量值就是sms.properties里配置的值。
3、spring cloud config 工作模式
配置项怎么配置? 通过配置文件进行配置并存储在git中
谁去读配置文件? configserver配置中心
应用系统中配置信息从哪来? 从configserver远程获取
3、全局刷新怎么实现的?
通过rabbitmq发送消息, 订阅的客户端(应用系统)收到消息后,判断是否需要刷新
具体实现后面spring cloud stream/bus会讲到

4、自动刷新是什么一个机制?
gitlab提交配置更新的时候,触发一个事件(项目-设置-集成-webhook)

发起http请求到config-server monitor组件
http://192.168.99.1:8888/monitor 这是配置中心地址

configserver解析请求,通过spring cloud bus消息总线发送通知给各服务(和/bus/refresh一样)
对应的webapi类:PropertyPathEndpoint#notifyByPath
5、安全机制:如何保证配置的保密性?
项目中的密码 不应该明文存储,应该是密文
configserver访问控制:用户名密码
文件内容加密:configserver中设置spring.cloud.config.server.encrypt.enabled=true
再配置一个秘钥:encrypt.key=12345678
配置文件中密文需要以{cipher}做为标识:如spring.rabbitmq.password= ‘{cipher}31010f99731d4bd8aa7e3ce76152b5686265e1160043aac7cf769c3c8e1bb7ef’

对应的web api:EncryptionController#encrypt 加密
EncryptionController#decrypt 解密

时间: 2024-11-07 01:15:21

springcloud config 分布式配置中心的相关文章

springcloud(九):配置中心和消息总线(配置中心终结版)

我们在springcloud(七):配置中心svn示例和refresh中讲到,如果需要客户端获取到最新的配置信息需要执行refresh,我们可以利用webhook的机制每次提交代码发送请求来刷新客户端,当客户端越来越多的时候,需要每个客户端都执行一遍,这种方案就不太适合了.使用Spring Cloud Bus可以完美解决这一问题. Spring Cloud Bus Spring cloud bus通过轻量消息代理连接各个分布的节点.这会用在广播状态的变化(例如配置变化)或者其他的消息指令.Spr

springcloud(七):配置中心svn示例和refresh

上一篇springcloud(六):配置中心git示例留了一个小问题,当重新修改配置文件提交后,客户端获取的仍然是修改前的信息,这个问题我们先放下,待会再讲.国内很多公司都使用的svn来做代码的版本控制,我们先介绍以下如何使用svn+Spring Cloud Config来做配置中心. svn版本 同样先示例server端的代码,基本步骤一样. 1.添加依赖 <dependencies> <dependency> <groupId>org.springframework

高可用的分布式配置中心(Spring Cloud Config)

上一篇内容讲述,一个服务如何从配置中心读取文件,配置中心如何从远程Git读取配置文件,当服务很多时,都需要同时从配置中心读取文件的时候,这时我们可以考虑将配置中心做成一个微服务,并且将其集群化,从而达到高可用,架构图如下: 一.准备工作 继续使用上一篇文章的工程,创建一个eureka-server工程,用作服务中心. 其pom.xml: <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&q

springcloud(六):配置中心git示例

随着线上项目变的日益庞大,每个项目都散落着各种配置文件,如果采用分布式的开发模式,需要的配置文件随着服务增加而不断增多.某一个基础服务信息变更,都会引起一系列的更新和重启,运维苦不堪言也容易出错.配置中心便是解决此类问题的灵丹妙药. 市面上开源的配置中心有很多,BAT每家都出过,360的QConf.淘宝的diamond.百度的disconf都是解决这类问题.国外也有很多开源的配置中心Apache的Apache Commons Configuration.owner.cfg4j等等.这些开源的软件

springcloud(八):配置中心服务化和高可用

在前两篇的介绍中,客户端都是直接调用配置中心的server端来获取配置文件信息.这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念.springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可. 这篇文章我们基于配置中心git版本

Spring Cloud之分布式配置中心

用服务的方式来实现 ConfigAppApplication.java package com.packtpub.ConfigApp; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuild

J360-cloud SpringCloud系列一:分布式配置服务器ConfigServer

分布式配置 Spring Cloud分布式配置服务由服务器端和客户端共同组成,Server端提供配置信息的存储管理,客户端完成配置信息的调度,工程结构如下 套用一个图来解释该部分在springCloud分布式系统中的结构 上面的图片说明了四个微服务以及各个服务之间的依赖关系. configuration service 处于最顶端,黄色标识,而且被其他微服务所依赖. discovery service 处于最低端,蓝色标识,同时也被其他服务所依赖. bootstrap.yml applicati

SpringCloud--分布式配置中心(Spring Cloud Config)

一.简介 在分布式系统中,spring cloud config 提供一个服务端和客户端去提供可扩展的配置服务.我们可用用配置服务中心区集中的管理所有的服务的各种环境配置文件.配置服务中心采用Git的方式存储配置文件,因此我们很容易部署修改,有助于对环境配置进行版本管理. 二.构建Config Server 创建一个spring-boot项目,取名为config-server,其pom.xml: ```<?xml version="1.0" encoding="UTF-

配置中心选型

     随着线上项目变的日益庞大,每个项目都散落着各种配置文件:因为采用分布式的开发模式,项目之间的相互引用随着服务的不断增多,相互之间的调用复杂度成指数升高,每次投产或者上线新的项目时苦不堪言,因此需要引用配置中心治理.   希望可以满足一下的条件: 1.集中配置,所以的配置文件集中到一个管理平台来治理 2.配置中心修改配置后,可以及时推送到客户端 3.支持大的并发查询   技术调研,配置中心目前有一些开源软件,如下: 1.Qihoo360/QConf 地址:https://github.c