基于Nacos的服务治理、配置中心

2022-04-06 15:45:24 浏览数 (1)

Nacos集群环境的搭建

参看《基于Docker搭建Nacos集群》:https://lupf.cn/articles/2020/05/21/1590058654840.html ;亦或者通过官方提供的其他方式安装,详情参考:https://nacos.io/zh-cn/docs/quick-start.html

Nacos作为配置中心
  • apollo配置中心 整理Nacos的服务治理,顺带着整理一下Nacos的配置中心;目前实际的生产使用的是Apollo;个人相比较更加喜欢Apollo一点,如果想了解Apollo的使用可参考:《SpringBoot集成Apollo配置中心(5分钟集成系列)》https://lupf.cn/articles/2019/11/19/1574169822114.html
  • 创建一个基础的SpringCloud项目,并添加一下配置
代码语言:javascript复制
 <properties>
      <java.version>1.8</java.version>
      <spring-cloud.version>Greenwich.SR5</spring-cloud.version>
      <spring-cloud-starter-alibaba-nacos-discovery.version>2.1.1.RELEASE
      </spring-cloud-starter-alibaba-nacos-discovery.version>
      <spring-cloud-starter-alibaba-nacos-config.version>2.1.1.RELEASE
      </spring-cloud-starter-alibaba-nacos-config.version>
  </properties>

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

      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <optional>true</optional>
      </dependency>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-test</artifactId>
          <scope>test</scope>
      </dependency>

      <!--Nacos配置中心-->
      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
          <version>${spring-cloud-starter-alibaba-nacos-config.version}</version>
      </dependency>

      <!--Nacos服务治理-->
      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
          <version>${spring-cloud-starter-alibaba-nacos-discovery.version}</version>
      </dependency>

      <!-- 服务的API -->
      <dependency>
          <groupId>com.lupf</groupId>
          <artifactId>nacos-api</artifactId>
          <version>0.0.1-SNAPSHOT</version>
      </dependency>
  </dependencies>

Nacos配置

  • dataId,用于匹配nacos中对应的配置文件 : 默认规则 ${spring.application.name}-${spring.profiles.active}.${file-extension} 如: nacos-provider-dev.yml ,如果没有环境区分就是nacos-provider.yml ;dataId允许根据自己的要求进行配置,具体如下
代码语言:javascript复制
# 规则: ${prefix}-${spring.profiles.active}-${spring.profiles.active}.${file-extension}
# 如下的配置最终匹配的配置文件为:nacos-provider-dev.yml  如果没有匹配上会去匹配nacos-provider.yml
spring: 
  application:
    name: nacos-provider
  cloud:
    nacos:
      config:
        server-addr: 192.168.1.160:8848,192.168.1.160:8848 # nacos的地址
        file-extension: yml # 配置文件的格式
        prefix: ${spring.application.name} # 配置文件的前缀 不配置默认使用的是
        group: DEFAULT_GROUP
  profiles:
    active: dev
  • group: 用于对配置文件进行分组
  • Nacos配置文件的命名规则
  • 添加nacos-provider.yml
代码语言:javascript复制
server:
  port: 9112
spring:
  application:
    name: nacos-provider
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848,192.168.1.162:8848
      config:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848,192.168.1.162:8848
key1: value1
profix_key1: value3
  • 添加nacos-consumer.yml
代码语言:javascript复制
server:
  port: 9113
spring:
  application:
    name: nacos-consumer
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848,192.168.1.162:8848
      config:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848,192.168.1.162:8848
  • 将启动文件application.yml修改为bootstrap.yml 并添加一下配置
代码语言:javascript复制
spring:
  application:
    name: nacos-provider
  cloud:
    nacos:
      config:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848 # nacos的地址
        file-extension: yml # 配置文件的格式
        prefix: ${spring.application.name} # 配置文件的前缀 不配置默认使用的是
        group: DEFAULT_GROUP
  profiles:
    active: dev
  • 启动项目
代码语言:javascript复制
// 出现以下日志说明配置文件加载成功
-06-16 :19:17.369  INFO [nacos-provider,,,]  --- [           main] c.a.c.n.c.NacosPropertySourceBuilder     : Loading nacos data, dataId: 'nacos-provider.yml', group: 'DEFAULT_GROUP', data: server:
  port: 
spring:
  application:
    name: nacos-provider
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848,192.168.1.162:8848
      config:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848,192.168.1.162:8848
key1: value1
profix_key1: value3
  • 添加配置文件获取的工具类 RemoteConfig // @RefreshScope 为自动刷新配置
代码语言:javascript复制
@Data
@Component
@RefreshScope
public class RemoteConfig {

    @Value ("${key1}")
    private String key1;

    @Value ("${profix_key1}")
    private String profixKey1;
}
  • 添加测试使用的NacosConfigController
代码语言:javascript复制
@RestController
@RequestMapping ("echo")
@Slf4j
public class NacosConfigController {
 @Autowired
    RemoteConfig remoteConfig;

 @GetMapping ("conf")
 public String echo() {
        log.info("provider rest conf resp {}", remoteConfig.toString());
 return remoteConfig.toString();
    }
}
服务治理
代码语言:javascript复制
http://127.0.0.1:9112/echo/conf
代码语言:javascript复制
// 直接修改nacos上的配置 将value3修改为value1 并发布
// 控制台会出现以下日志
-06-16 :29:11.216  INFO [nacos-provider,,,]  --- [.168.1.208_8848] o.s.c.e.event.RefreshEventListener       : Refresh keys changed: [profix_key1]

// 再次刷新,发现值已经修改成功了
服务治理
RestFul API

provider就使用上面 echo/conf接口作为测试接口

  • 添加命名空间
  • 配置将服务发布到指定命名空间
代码语言:javascript复制
spring:
    cloud:
        nacos:
            discovery:
                namespace: local
  • provider和consumer添加配置文件
代码语言:javascript复制
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.1.160:8848,192.168.1.161:8848,192.168.1.162:8848
  • provider和consumer启动类添加以下注解
代码语言:javascript复制
@EnableDiscoveryClient
  • consumer实例化RestTemplate
代码语言:javascript复制
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
    return new RestTemplate();
}
  • 测试RestFulController
代码语言:javascript复制
@RestController
@RequestMapping ("rest")
@Slf4j
public class RestFulController {
    @Autowired
    RestTemplate restTemplate;

    @GetMapping ("conf")
    public String echo() {
        log.info("consumer rest conf req start....");
        return restTemplate.getForObject("http://nacos-provider/echo/conf", String.class);
    }
}
  • 启动服务,nacos中可以看到如下的服务
  • 测试
代码语言:javascript复制
http://127.0.0.1:9113/rest/conf
  • 服务的命名空间 当不同的环境需要进行区分的时候,如开发环境、测试环境、正式环境;那么这些环境下的服务可能是有区别且不能穿插调用,因此我们就可以通过命名空间各个服务进行隔离;
整合feign的服务治理
  • nacos-api添加fiegn的请求及响应对象已经对应的service
代码语言:javascript复制
@Data
@AllArgsConstructor
public class ReqBean implements Serializable {
    private String name;

    private String msg;
}

@Data
@AllArgsConstructor
public class RespBean implements Serializable {
    private String code;

    private String msg;
}

@FeignClient (value = "nacos-provider", path = "/api", fallback = FeignService.DefaultFallback.class)
public interface FeignService {

    @PostMapping ("/hello")
    RespBean hello(@RequestBody ReqBean reqBean);

    @PostMapping ("/hi")
    String hi(@RequestParam (value = "name") String name);

    class DefaultFallback implements FeignService {

        @Override
        public RespBean hello(ReqBean reqBean) {
            return new RespBean("-1", "ERR");
        }

        @Override
        public String hi(String name) {
            return "hello name";
        }
    }
}
  • provider和consumer模块添加api模块
代码语言:javascript复制
<dependency>
<groupId>com.lupf</groupId>
<artifactId>nacos-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
  • provider和consumer添加以下注解,开启feign
代码语言:javascript复制
@EnableFeignClients (basePackages = "com.lupf.*")
  • provider实现FeignService
代码语言:javascript复制
@Service
@Slf4j
public class FeignServiceImpl implements FeignService {
@Override
public RespBean hello(ReqBean reqBean) {
    log.info("provider feign hello reqBean:{}", reqBean.toString());
 return new RespBean("0", "success");
}

@Override
public String hi(String name) {
    log.info("provider feign hi req name:{}", name);
 return "hi:"   name;
}
}
  • provider添加对外暴露的controller;注意,路径、参数需要和FeignService配置的路径一致
代码语言:javascript复制
RestController
@RequestMapping ("api")
public class FeignController {
@Qualifier ("feignServiceImpl")
@Autowired
FeignService feignService;

@PostMapping ("hello")
public RespBean trans(@RequestBody ReqBean reqBean) {
    return feignService.hello(reqBean);
}

@PostMapping ("hi")
public String hello(String name) {
    return feignService.hi(name);
}
}
  • consumer的调用FeignController
代码语言:javascript复制
@RestController
@RequestMapping ("feign")
@Slf4j
public class FeignController {

@Autowired (required = false)
FeignService feignService;

@GetMapping ("hello")
public String hello() {
    log.info("consumer feign hello request start....");
    ReqBean reqBean = new ReqBean("张三", "hello");
    RespBean trans = feignService.hello(reqBean);
    log.info("consumer feign hello request return:{}", trans.toString());
    return trans.toString();
}

@GetMapping ("hi")
public String hi() {
    log.info("consumer feign hi request start....");
    String zhang_san = feignService.hi("zhang san");
    log.info("consumer feign hi request return:{}", zhang_san);
    return zhang_san;
}
}
  • 测试
代码语言:javascript复制
http://127.0.0.1:9113/feign/hello
http://127.0.0.1:9113/feign/hello
dubbo服务的治理
  • 添加dubbo的引用
代码语言:javascript复制
<spring-cloud-starter-dubbo.version>2.1.1.RELEASE</spring-cloud-starter-dubbo.version>

<dependency>
    <!--<groupId>org.springframework.cloud</groupId>-->
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-dubbo</artifactId>
    <version>${spring-cloud-starter-dubbo.version}</version>
</dependency>
  • nacos的nacos-provider.yml和nacos-consumer.yml添加一下配置
代码语言:javascript复制
dubbo:
  application:
    qos-enable: false
  consumer:
    check: false
  protocol:
    name: dubbo
    port: -1
  reference:
    check: false
  registry:
    address: spring-cloud://localhost
    check: false
  scan:
    base-packages: com.lupf

dubbo.scan.base-packages 为你的包路径

  • provider添加Dubbo的具体实现
代码语言:javascript复制
// 注意,这里的Service为:org.apache.dubbo.config.annotation.Service 不是Spring的service
@Service
@Slf4j
public class DubboServiceImpl implements DubboService {
    @Override
    public RespBean hello(ReqBean reqBean) {
        log.info("provider reqBean:{}", reqBean.toString());
        return new RespBean("999", "dubbo success");
    }
}
  • consumer创建测试DubboController
代码语言:javascript复制
@RestController
@RequestMapping ("dubbo")
@Slf4j
public class DubboController {
    @Reference
    DubboService dubboService;

    @GetMapping ("hello")
    public String hello() {
        log.info("consumer dubbo request start....");
        ReqBean reqBean = new ReqBean("张三", "hello");
        RespBean trans = dubboService.hello(reqBean);
        log.info("consumer dubbo request return:{}", trans.toString());
        return "success";
    }
}
  • 测试
代码语言:javascript复制
http://127.0.0.1:9113/dubbo/hello

sleuth链路追踪
  • 引入sleuth依赖
代码语言:javascript复制
<spring-cloud-starter-sleuth.version>2.1.0.RELEASE</spring-cloud-starter-sleuth.version>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
    <version>${spring-cloud-starter-sleuth.version}</version>
</dependency>
  • 请求测试
dubbo的链路追踪

添加一个dubbo zipkin的依赖

  • 2.7.0之前的版本
代码语言:javascript复制
<brave-instrumentation-dubbo-rpc.version>5.10.0</brave-instrumentation-dubbo-rpc.version>

<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-dubbo-rpc</artifactId>
    <version>${brave-instrumentation-dubbo-rpc.version}</version>
</dependency>

  • 大于等于 2.7.0之前的版本
代码语言:javascript复制
<brave-instrumentation-dubbo.version>5.10.0</brave-instrumentation-dubbo.version>

<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-dubbo</artifactId>
    <version>${brave-instrumentation-dubbo.version}</version>
</dependency>
Nacos常见问题
导致log4j2不打印日志日志的问题
  • 错误描述
代码语言:javascript复制
WARN No Root logger was configured, creating default ERROR-level Root logger with Console appender
  • 解决方式,启动类添加配置
代码语言:javascript复制
public static void main(String[] args) {
 // 因为nacos的log4j2导致本项目的日志不输出的问题
 // 配置关闭nacos日志
  System.setProperty("nacos.logging.default.config.enabled", "false");
  SpringApplication.run(xxxx.class, args);
}
Nacos频繁的心跳日志

服务频繁的心跳导致较多无效的日志输出

  • 提升nacos的日志级别,使其不输出
代码语言:javascript复制
logging.level.com.alibaba.nacos.client.naming=error

0 人点赞