ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Nacos[转]

2022-03-28 21:33:46  阅读:230  来源: 互联网

标签:spring 配置 Nacos nacos config cloud


Nacos是一款集服务注册发现、服务配置和管理于一身的开源软件,这节主要记录Nacos的服务注册发现功能的使用。借助Spring Cloud Alibaba Nacos Discovery,我们可以轻松地使用Spring Cloud编程模型体验Nacos的服务注册发现功能。本节使用的Spring Cloud版本为Hoxton.SR3,Spring Cloud Alibaba版本为2.2.0.RELEASE,Spring Boot版本为2.2.3.RELEASE。

Nacos安装

因为Spring Cloud Alibaba 2.2.0.RELEASE内置的Nacos client版本为1.1.4,所以我们使用这个版本的Nacos。Nacos下载地址:https://github.com/alibaba/nacos/releases,选择nacos-server-1.1.4.zip 下载并解压:

QQ20200313-095737@2x

解压后,打开conf目录下的配置文件,在末尾添加数据源配置:

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456

然后在MySQL数据库中新建nacos数据库,并导入Nacos解压包conf目录下的nacos-mysql.sql脚本,导入后,库表如下图所示:

QQ20200313-100402@2x

数据层准备好后,我们就可以启动Nacos了。笔者的电脑为Mac,所以这里以Unix环境为例。终端切换到Nacos解压目录下的bin目录,然后执行sh startup.sh -m standalone启动单机版Nacos。

为了方便,我们也可以创建一个run.sh脚本:

#/bin/bash
sh shutdown.sh
sh startup.sh -m standalone
tail -10f /Users/mrbird/Desktop/nacos/logs/start.out

其中/Users/mrbird/Desktop/nacos为我的Nacos解压目录。启动后,浏览器访问:http://localhost:8848/nacos/#/login:

QQ20200313-101410@2x

说明Nacos启动成功,账号密码都为nacos。

注册中心

框架搭建

使用IDEA创建一个maven项目,artifactId为spring-cloud-alibaba-nacos-register,然后在其下面创建两个Module(Spring Boot项目),artifactId分别为consumer和provider,充当服务消费端和服务提供端,项目结构如下图所示:

QQ20200313-103900@2x

spring-cloud-alibaba-nacos-register的pom内容:

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <groupId>cc.mrbird</groupId>
    <artifactId>spring-cloud-alibaba-nacos-register</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>provider</module>
        <module>consumer</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
        <com-alibaba-cloud.version>2.2.0.RELEASE</com-alibaba-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${com-alibaba-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

因为本节演示的是Nacos的服务注册发现功能,所以引入的是spring-cloud-alibaba-nacos-discovery依赖。

provider的pom的内容如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cc.mrbird</groupId>
        <artifactId>spring-cloud-alibaba-nacos-register</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>provider</artifactId>
    <name>provider</name>
    <description>服务提供端</description>

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

consumer的pom内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cc.mrbird</groupId>
        <artifactId>spring-cloud-alibaba-nacos-register</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath>
    </parent>

    <artifactId>consumer</artifactId>
    <name>consumer</name>
    <description>服务消费端</description>

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

Nacos作为注册中心

在provider的cc.mrbird.provider目录下新建controller包,然后在该包下新建HelloController

@RestController
@RequestMapping("provide")
public class HelloController {

    @GetMapping("{message}")
    public String hello(@PathVariable String message) {
        return String.format("hello %s", message);
    }
}

提供了一个REST接口,供consumer调用。

然后在provider的项目配置文件application.yml里添加如下配置:

server:
  port: 8001
spring:
  application:
    name: provider
  cloud:
    nacos:
      server-addr: localhost:8848
  • server.port,provider服务端口为8001;
  • spring.application.name,服务名称为provider
  • spring.cloud.nacos.server-addr,指定Nacos注册中心的地址。

provider代码准备好后,接着在consumer项目的cc.mrbird.consumer目录下新建controller包,然后在该包下新建ConsumeController

@RestController
@RequestMapping("consume")
public class ConsumeController {

    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("hello/{message}")
    public String hello(@PathVariable String message) {
        ServiceInstance serviceInstance = loadBalancerClient.choose("provider");
        String path = String.format("http://%s:%s/provide/%s", serviceInstance.getHost(), serviceInstance.getPort(), message);
        String result = restTemplate.getForObject(path, String.class);
        return String.format("%s from %s %s", result, serviceInstance.getHost(), serviceInstance.getPort());
    }
}

因为spring-cloud-alibaba-nacos-discovery内置了Ribbon,所以我们可以直接注入LoadBalancerClientRestTemplate我们稍后再配置。hello()方法中我们通过服务提供者的名称provider(即provider项目配置的spring.application.name)从Nacos注册中心中获取对应的服务实例,然后访问其提供的/provide/{message} GET服务。这些在Spring Cloud Ribbon客户端负载均衡一节中都介绍过了,有不懂的可以参阅下。

接着在consumer项目的cc.mrbird.consumer目录下新建configure包,然后在该包下新建ConsumerConfigure

@Configuration
public class ConsumerConfigure {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

上面代码配置了RestTemplate Bean。

最后在consumer项目的配置文件application.yml中添加如下配置:

server:
  port: 9001
spring:
  application:
    name: consumer
  cloud:
    nacos:
      server-addr: localhost:8848

配置和provider项目类似,不再赘述。

分别启动provider和consumer项目:

QQ20200313-122632@2x

观察Nacos控制台服务列表:

QQ20200313-122748@2x

可以看到,两个服务都注册进来了。接着浏览器访问:http://localhost:9001/consume/hello/nacos:

QQ20200313-122916@2x

调用成功,说明服务发现成功。

测试负载均衡

如下图所示,在ProviderApplication上右键选择Copy Configuration…:

QQ20200313-123539@2x

然后按照下图所示填写相关内容:

QQ20200313-123806@2x

点击ok保存后,启动它:

QQ20200313-123912@2x

观察Nacos控制台,可以看到provider已经有两个实例了:

QQ20200313-124004@2x

然后多次访问:http://localhost:9001/consume/hello/nacos,可以看到请求是均衡的(默认为轮询算法):

2020-03-13 12.54.05.gif

Nacos注册中心配置

更多可用Nacos Descovery配置:

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.discovery.server-addr Nacos Server 启动监听的ip地址和端口
服务名 spring.cloud.nacos.discovery.service ${spring.application.name} 给当前的服务命名
服务分组 spring.cloud.nacos.discovery.group DEFAULT_GROUP 设置服务所处的分组
权重 spring.cloud.nacos.discovery.weight 1 取值范围 1 到 100,数值越大,权重越大
网卡名 spring.cloud.nacos.discovery.network-interface 当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址
注册的IP地址 spring.cloud.nacos.discovery.ip 优先级最高
注册的端口 spring.cloud.nacos.discovery.port -1 默认情况下不用配置,会自动探测
命名空间 spring.cloud.nacos.discovery.namespace 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
AccessKey spring.cloud.nacos.discovery.access-key 当要上阿里云时,阿里云上面的一个云账号名
SecretKey spring.cloud.nacos.discovery.secret-key 当要上阿里云时,阿里云上面的一个云账号密码
Metadata spring.cloud.nacos.discovery.metadata 使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
日志文件名 spring.cloud.nacos.discovery.log-name
集群 spring.cloud.nacos.discovery.cluster-name DEFAULT 配置成Nacos集群名称
接入点 spring.cloud.nacos.discovery.enpoint UTF-8 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否集成Ribbon ribbon.nacos.enabled true 一般都设置成true即可
是否开启Nacos Watch spring.cloud.nacos.discovery.watch.enabled true 可以设置成false来关闭 watch

本节源码链接:https://github.com/wuyouzhuguli/SpringAll/tree/master/74.spring-cloud-alibaba-nacos-register。

参考自官方文档:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_discovery

配置中心

上一节Spring Cloud Alibaba Nacos注册中心记录了Nacos作为注册中心的使用方式,这节继续记录下Nacos作为配置中心的使用方式。本节使用的Spring Cloud版本为Hoxton.SR3,Spring Cloud Alibaba版本为2.2.0.RELEASE,Spring Boot版本为2.2.3.RELEASE。

框架搭建

新建一个Spring Boot项目,artifactId为spring-cloud-alibaba-nacos-config,项目结构如下图所示:

QQ20200313-161613@2x

项目的pom内容:

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>cc.mrbird</groupId>
    <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-cloud-alibaba-nacos-config</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR3</spring-cloud.version>
        <com-alibaba-cloud.version>2.2.0.RELEASE</com-alibaba-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${com-alibaba-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

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

因为这节记录的是Nacos作为配置中心的功能,所以引入的是spring-cloud-alibaba-nacos-config依赖。

基本使用

在项目配置文件application.yml中添加如下配置:

server:
  port: 8080
spring:
  application:
    name: my-project

上面配置指定应用端口为8080,应用名称为my-project。

接着在resources目录下新建配置文件bootstrap.yml,在里面添加如下Nacos config配置(必须在bootstrap.yml中配置,bootstrap.yml优先级比application.yml高):

spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        file-extension: yaml
  • spring.cloud.nacos.config.server-addr配置了Nacos配置中心的地址,也可以通过spring.cloud.nacos.server-addr指定,它们两个是等价的;
  • spring.cloud.nacos.config.file-extension指定待会在Nacos配置中心读取的配置的格式为yaml格式。

我们回到Nacos控制台http://localhost:8848/nacos,在配置列表中新建一个配置:

QQ20200316-091128@2x

QQ20200316-091434@2x

我们新建了一个my-project.yaml配置(dataId为my-project.yaml,group为DEFAULT_GROUP,它们的具体含义下面会介绍到),配置了message: 'hello nacos config',创建好后,点击发布即可。

接着回到我们的项目,在cc.mrbird.nacos目录下新建controller包,然后在该包下新建TestController用于测试配置获取规则:

@RestController
@RefreshScope
public class TestController {

    @Value("${message:null}")
    private String message;

    @GetMapping("message")
    public String getMessage() {
        return this.message;
    }
}

上面代码我们从刚刚在Nacos控制台配置的配置文件中获取message配置的值,@RefreshScope用于刷新配置,即我们在Nacos控制台修改了相关配置点击发布后,我们的应用能够在不重启的情况下获取到最新的配置。

启动项目,在浏览器中访问:http://localhost:8080/message:

QQ20200316-092401@2x

配置获取成功,在Nacos控制台中将message值修改为hello world后发布,再次访问http://localhost:8080/message:

QQ20200316-092754@2x

获取配置规则

Nacos配置中心通过namespace、dataId和group来唯一确定一条配置。

  1. namespace,即命名空间。默认的命名空间为public,我们可以在Nacos控制台中新建命名空间;

  2. dataId,即配置文件名称,dataId的拼接格式如下:

    ${prefix} - ${spring.profiles.active} . ${file-extension}
    
    • prefix默认为pring.application.name的值,也可以通过配置项spring.cloud.nacos.config.prefix来配置;
    • spring.profiles.active即为当前环境对应的profile注意,当spring.profiles.active为空时,对应的连接符-也将不存在,dataId的拼接格式变成${prefix}.${file-extension}
    • file-extension为配置内容的数据格式,可以通过配置项spring.cloud.nacos.config.file-extension来配置。
  3. group,即配置分组,默认为DEFAULT_GROUP,可以通过spring.cloud.nacos.config.group配置。

所以根据这些规则,上面示例中我们的应用名称spring.application.name为my-project,spring.cloud.nacos.config.file-extension的值为yaml,没有指定spring.profiles.active,于是dataId为my-project.yaml,分组为默认的DEFAULT_GROUP,命名空间为默认的public。这就是我们在Nacos控制台中新建配置时的根据。

配置划分实战

Nacos配置中心的namespace、dataId和group可以方便灵活地划分配置。比如,我们现在有一个项目需要开发,项目名称为febs,项目开发人员分为两个组:GROUP_A和GROUP_B,项目分为三个环境:开发环境dev、测试环境test和生产环境prod。

假如现在GROUP_A组的组长需要在Nacos中新建一个开发环境的febs项目配置,那么他可以这样做:

  1. 在Nacos控制台中新建一个名称为febs的命名空间:

QQ20200316-094921@2x

QQ20200316-094952@2x

QQ20200316-095015@2x

新建febs命名空间后,会生成一个唯一标识该命名空间的命名空间id2ef2186e-078c-4904-8643-ff5e90555456

  1. 在Nacos控制台中新建一个配置:

QQ20200316-100032@2x

QQ20200316-095417@2x

  1. 最后在febs项目的bootstrap.yml配置文件中添加如下配置即可:

    spring:
      profiles:
        active: dev
      cloud:
        nacos:
          config:
            server-addr: localhost:8848
            file-extension: yaml
            prefix: febs
            namespace: '2ef2186e-078c-4904-8643-ff5e90555456'
            group: GROUP_A
    

QQ20200316-100224@2x

配置回滚

Nacos中,修改配置点击发布后会创建一个对应的历史版本快照,我们可以在Nacos控制台的历史版本列表中找到这些快照:

QQ20200316-100425@2x

点击回滚按钮即可将配置恢复到指定的版本。

获取多个配置

除了通过上面的方式指定一个唯一配置外,我们还可以同时获取多个配置文件的内容,比如,将项目的bootstrap.yml内容修改为:

spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        extension-configs:
          - dataId: ext-config-one.yaml
            group: DEFAULT_GROUP
            refresh: true
          - dataId: ext-config-two.yaml
            group: DEFAULT_GROUP
            refresh: false
  • spring.cloud.nacos.config.extension-configs[n].dataId,指定多个配置的dataId,必须包含文件格式,支持properties、yaml或yml;
  • spring.cloud.nacos.config.extension-configs[n].group,指定分组;
  • spring.cloud.nacos.config.extension-configs[n].refresh,是否支持刷新。

上面的配置中,我们分别从DEFAULT_GROUP中获取了ext-config-one.yamlext-config-two.yaml配置内容,并且ext-config-one.yaml支持刷新,ext-config-two.yaml不支持刷新。

没有namespace的配置,言外之意就是Nacos目前还不支持多个配置指定不同的命名空间。

我们在Nacos控制台中新建这两个配置:

QQ20200316-105741@2x

ext-config-one.yaml配置内容:

ext1: 'hello'

ext-config-two.yaml配置内容:

ext2: 'world'

在项目的TestController中添加:

@RestController
@RefreshScope
public class TestController {

    @Value("${ext1:null}")
    private String ext1;
    @Value("${ext2:null}")
    private String ext2;

    @GetMapping("multi")
    public String multiConfig() {
        return String.format("ext1: %s ext2: %s", ext1, ext2);
    }

    ...
}

启动项目,浏览器访问:http://localhost:8080/multi:

QQ20200316-112930@2x

ext1的值修改为niceext2的值修改为job

QQ20200316-113120@2x

可以看到ext1的值更新了,ext2没有更新。

多配置共享

多配置共享其实和获取多个文件配置作用差不多,下面演示下多配置共享。

将bootstrap.yml配置修改为:

spring:
  cloud:
    nacos:
      config:
        server-addr: localhost:8848
        shared-configs: ext-config-one.yaml,ext-config-two.yaml

spring.cloud.nacos.config.shared-configs指定了共享ext-config-one.yamlext-config-two.yaml的配置。

重启项目,访问http://localhost:8080/multi:

QQ20200316-134742@2x

也可以正常获取。

可以看到,无论是多配置共享还是获取多个配置,要完成的事情是一样的,不过它们都有各自的局限性。多配置共享无法指定分组、无法指定命名空间、无法配置是否刷新;获取多个配置相对较为灵活,不过也不能配置命名空间。具体相关的讨论可以参考:https://github.com/alibaba/spring-cloud-alibaba/issues/141

常用配置

配置项 key 默认值 说明
服务端地址 spring.cloud.nacos.config.server-addr
DataId前缀 spring.cloud.nacos.config.prefix spring.application.name
Group spring.cloud.nacos.config.group DEFAULT_GROUP
dataID后缀及内容文件格式 spring.cloud.nacos.config.file-extension properties dataId的后缀,同时也是配置内容的文件格式,目前只支持 properties
配置内容的编码方式 spring.cloud.nacos.config.encode UTF-8 配置的编码
获取配置的超时时间 spring.cloud.nacos.config.timeout 3000 单位为 ms
配置的命名空间 spring.cloud.nacos.config.namespace 常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源隔离等。
AccessKey spring.cloud.nacos.config.access-key
SecretKey spring.cloud.nacos.config.secret-key
相对路径 spring.cloud.nacos.config.context-path 服务端 API 的相对路径
接入点 spring.cloud.nacos.config.endpoint 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否开启监听和自动刷新 spring.cloud.nacos.config.refresh.enabled true

参考链接:

https://github.com/alibaba/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/nacos-example/nacos-config-example/readme-zh.md

https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html#_spring_cloud_alibaba_nacos_config

本节源码链接:https://github.com/wuyouzhuguli/SpringAll/tree/master/75.spring-cloud-alibaba-nacos-config。

标签:spring,配置,Nacos,nacos,config,cloud
来源: https://www.cnblogs.com/bgtong/p/16069195.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有