栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringCloud整合Nacos注册中心和配置中心

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringCloud整合Nacos注册中心和配置中心

整合nacos配置中心的文章https://blog.csdn.net/rocklee/article/details/124299187

以下是SpringCloud整合Nacos注册中心的步骤

目录
  • SpringCloud的架构
  • API模块
  • 提供服务
    • 依赖
    • 配置文件
    • api实现
  • 消费者
    • 依赖
    • 配置文件
    • 配置类
    • 拦截
    • ribbon方式调用
    • feign方式调用
      • api实现
      • 调用

SpringCloud的架构

先说一下版本问题,本文引用框架的版本如下:
boot: 2.4.2
nacos: 2021.1
spring-cloud: 2020.0.5

API模块

相对来讲SpringCloud跟Dubbo类似的做法,也需要将api的接口独立出来,如easy-cloud-api。

比如我在这里定义一个TestService,要注意的是SpringCloud跟Dubbo不一样,它跑的协议和普通的boot应用一样,用的是restful,所以需要用到web的注解,所以我们需要将一些provider和consumer都需要用到的web注解都放到接口里面,省得两边都打,比如下面的@GetMapp和@RequestParam等。

public interface TestService {
  @GetMapping("/test")
  public Object test(@RequestParam("who") String who);
}
提供服务 依赖

SpringCloud的Provider端就是一标准的Springboot应用,但是要加入cloud的发现服务,我选择nacos作为服务自治中心,因此要改pom依赖,增加

    
            com.alibaba.cloud
            spring-cloud-starter-alibaba-nacos-discovery
    
配置文件

再修改bootstrap.yml,加上cloud的配置参数:

server:
  tomcat:
    accept-count: 800 #如果max线程都满负载工作,还能接受多少排队任务
    threads:
      max: 200 #最大线程数
      min-spare: 12 #核心线程数
    max-connections: 5000
  port: 2000


spring:
  #main: #不引用org.springframework.boot:spring-boot-starter-web就好
  #  web-application-type: none
  application:
    name: ${services.account-service}
  profiles:
    include: jdbc,config

  output:
    ansi:
      enabled: always
  cloud:
    inetutils:
      preferred-networks: 128.30
    nacos:
      username: seata
      password: seatapass
      config:
        server-addr: ${nacos.server-addr}
        #文件扩展名默认就是properties,还可以是yaml
        file-extension: yml
        refresh-enabled: true
        #name: spec-config.yml
        
      discovery:
        server-addr: ${nacos.server-addr}
        service: ${services.account-service}


api实现

接着写TestServie的实现,也就是一Controller,注意TestService接口里面有的注解,这里就不用再重复:

@RestController
@RequestMapping("/test")
public class TestController implements TestService {
  @Resource
  private DiscoveryClient discoveryClient;
  @Resource
  private Registration registration;
  public Object test(@RequestParam("who") String who){
    List instance=discoveryClient.getInstances(registration.getServiceId()) ;
    return SentinelResponseEntity.fromResult(0,"Hello,"+who+",Test OK,"+new Date()+"n"+
            instance.stream().map(i->i.getUri()+"/"+i.getServiceId()).
                    collect(Collectors.joining(","))
    );
  }
}

最后在启动类加上@EnableDiscoveryClient即可。

消费者 依赖

因为要用feignclient和负载平衡,所以要引入pom依赖:

        
            com.alibaba.cloud
            >spring-cloud-starter-alibaba-nacos-discovery
        

        
            org.springframework.cloud
            >spring-cloud-starter-loadbalancer
        
        
            org.springframework.cloud
            >spring-cloud-starter-openfeign
        
配置文件

和服务端差不多,spring.application.name要改为自己的名称,spring.cloud.nacos.discovery.service要改为要引用的服务的名称,如果要引用多个微服务,用逗号分隔,如 s e r v i c e s . a c c o u n t − s e r v i c e , {services.account-service}, services.account−service,{services.order-service}

配置类

先写配置类,声明一个有负载平衡功能的resttemplate,并实现无论用ribbon还是feign来调用微服务都能进行调用拦截(方便加入token之类的额外信息)

@Configuration
public class OrderServiceConfig implements ApplicationListener {
 
  @Bean
  @LoadBalanced
  public RestTemplate restTemplate(){
    RestTemplate restTemplate=new RestTemplate();
    return restTemplate;
  }
  @Bean
  public TokenRequestInterceptor tokenRequestInterceptor(){
    return new TokenRequestInterceptor();
  }
  @PostConstruct
  public void init(){
    //System.out.println(service);
  }

  @Override
  public void onApplicationEvent(ApplicationReadyEvent event) {
    扫描所有ribbon实现并加入拦截
    event.getApplicationContext().getBeansOfType(RestTemplate.class).entrySet().forEach(e->{
      e.getValue().getInterceptors().add(new ClientHttpRequestTokenInterceptor());
    });
  }
}
拦截

下面是ribbon的拦截,模拟在header里面加入token

@Slf4j
public class ClientHttpRequestTokenInterceptor implements ClientHttpRequestInterceptor {
    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
      log.info("===request: {}", request.getURI());
      request.getHeaders().set("token", "abc123");
      return execution.execute(request, body);
    }
}

下面是feign请求的全局拦截

@Slf4j
public class TokenRequestInterceptor implements RequestInterceptor {
  @Override
  public void apply(RequestTemplate template) {
    log.info("{}",template.header("token","abc123"));
  }
}
ribbon方式调用

先确保服务方至少有一实例在运行

@Resource
private RestTemplate restTemplate;
@Value("${services.account-service}")
private String serviceId;
@Test
  public void remoteCall(){
    String who="陈大文";
    String url = "http://"+serviceId + "/test/test?who=" + who;
    String result = restTemplate.getForObject(url, String.class);
    System.out.println("Invoke : " + url + ", return : " + result);
  }

执行结果显示,拦截器有输出具体调用的url,调用也正常:

2022-04-20 09:03:39.765  INFO 21340 --- [           main] .f.s.o.ClientHttpRequestTokenInterceptor : ===request: http://128.30.202.25:2000/test/test?who=%E9%99%88%E5%A4%A7%E6%96%87
Invoke : http://easy-cloud-account-service/test/test?who=陈大文, return : {errCode=0, result=Hello,陈大文,Test OK,Wed Apr 20 09:03:50 CST 2022
http://128.30.202.25:2000/easy-cloud-account-service, id=0}
feign方式调用 api实现

建一个Feign的实现接口,因为格式要严格与服务端一致所以直接继承好了,加上consumer的注解即可使用:

@Service
@FeignClient(value = "${services.account-service}/test")
public interface TestService extends com.freestyle.easyspringcloud.api.service.TestService {
}
调用
@Resource
private TestService testService;
@Test
  public void testFeign(){
    Object entity= testService.test("陈大文");
    System.out.println(entity);
  }

执行结果:

2022-04-20 09:10:24.446  INFO 31108 --- [           main] c.f.s.order.TokenRequestInterceptor      : GET /test?who=%E9%99%88%E5%A4%A7%E6%96%87 HTTP/1.1
token: abc123

Binary data
{errCode=0, result=Hello,陈大文,Test OK,Wed Apr 20 09:10:24 CST 2022
http://128.30.202.25:2000/easy-cloud-account-service, id=0}

可见,feign的拦截中的RequestTemplate并不能显示具体调用哪个实例的api,如果有需要,则自己配置feign Client,因为l默认的FeignBlockingLoadBalancerClient.java:88在execute时才确定用哪个实例:

ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);
		org.springframework.cloud.client.loadbalancer.Response lbResponse = new DefaultResponse(
				instance);
                ....
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/821165.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号