SpringCloud第二天

初体验springcloud微服务不同模块之间的服务调用

在order模块,创建一个controller,用于调用video模块的api


@RestController
@RequestMapping("api/v1/video_order")
public class OrderController {


    @Autowired
    private RestTemplate restTemplate;


    @RequestMapping("/save")
    public Object save(int videoId){

        Video video = restTemplate.getForObject("http://localhost:9000/api/v1/video/find_by_id?videoId="+videoId, Video.class);

        VideoOrder videoOrder = new VideoOrder();
        videoOrder.setVideoId(video.getId());
        videoOrder.setVideoTitle(video.getTitle());
        videoOrder.setCreateTime(new Date());
        return videoOrder;

    }
}

在启动函数中添加@Bean注解方法,RestTemplate就是可以获得别的模块Api的类

@SpringBootApplication
public class OrderApplication {
    public static void main(String [] args){

        SpringApplication.run(OrderApplication.class,args);
    }
    @Bean
    public RestTemplate getRestTemplate(){

        return new RestTemplate();
    }
}

在video模块中,controller

@RestController
@RequestMapping("api/v1/video")
public class VideoController {
    @Autowired
    private VideoService videoService;
    @RequestMapping("find_by_id")
    public Object findById(int videoId){

        return videoService.findById(videoId);
    }

}

两个模块都运行之后,访问 localhost:8000/api/v1/video_order/save?videoId=40发现成功

缺点

  • 服务之间的IP信息写死
  • 服务之间⽆法提供负载均衡
  • 多个服务直接关系调⽤维护复杂

通过Nacos来管理微服务

  • 服务注册:服务提供者provider,启动的时候向注册中
    ⼼上报⾃⼰的⽹络信息
  • 服务发现:服务消费者consumer,启动的时候向注册中⼼上报⾃⼰的⽹络信息,拉取provider的相关⽹络信息
  • 核⼼:服务管理,是有个服务注册表,⼼跳机制动态维护,服务实例在启动时注册到服务注册表,并在关闭时注销。
  • 微服务应⽤和机器越来越多,调⽤⽅需要知道接⼝的⽹络地址,如果靠配置⽂件的⽅式去控制⽹络地址,对于动态新增机器,维护带来很⼤问题

使用方法

下载nacos安装包之后,解压,在bin目录启动
sh startup.sh -m standalone
然后浏览器访问 localhost:8848/nacos,默认账号密码都是nacos

然后再在每个服务模块添加依赖

<dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

每个application.yml文件添加配置


spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848

然后再在每个启动类上添加注解
@EnableDiscoveryClient
然后再在Order的controller中更改

@RestController
@RequestMapping("api/v1/video_order")
public class OrderController {
    @Autowired
    private DiscoveryClient discoveryClient; //通过它可以获得请求的url和端口号

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("save")
    public VideoOrder save(int videoId){
        VideoOrder videoOrder = new VideoOrder();
        videoOrder.setVideoId(videoId);
        //获取到对应的服务的相关信息
        List<ServiceInstance> list = discoveryClient.getInstances("wpb-video-service");
        ServiceInstance si = list.get(0);
        //通过ServiceInstance获取到他的url和端口号,这些信息都在nacos中注册过了
        Video video = restTemplate.getForObject("http://"+si.getHost()+":"+si.getPort()+
                "/api/v1/video/find_by_id?videoId="+videoId,Video.class);
        videoOrder.setVideoTitle(video.getTitle());
        videoOrder.setVideoId(video.getId());
        return videoOrder;
    }
}

然后重启项目可以看到

通过postman测试成功

不过这个时候并没有考虑到负载均衡的问题,对于一个服务来说依然只是一台服务器,常见的负载均衡策略有

  • 节点轮询
    -- 简介:每个请求按顺序分配到不同的后端服务器
  • weight 权重配置
    -- 简介:weight和访问比率成正比,数字越大,分配得到的流量越高
  • 固定分发
    -- 简介:根据请求按访问ip的hash结果分配,这样每个用户就可以固定访问一个后端服务器

Ribbon的使用

Ribbon是一个客户端负载均衡工具,通过Spring Cloud封装,可以轻松和AlibabaCloud整合
使用也比较简单,在order的启动类

      @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate(){

        return new RestTemplate();
    }

其他的不变,这样就开启了负载均衡
Ribbon支持的负载均衡策略介绍

然后使用的话有一个注意点,在order模块调用的时候


@RestController
@RequestMapping("api/v1/video_order")
public class OrderController {
    @Autowired
    private DiscoveryClient discoveryClient; //通过它可以获得请求的url和端口号

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("save")
    public VideoOrder save(int videoId){
        VideoOrder videoOrder = new VideoOrder();
        videoOrder.setVideoId(videoId);
        //获取到对应的服务的相关信息
        List<ServiceInstance> list = discoveryClient.getInstances("wpb-video-service");
        ServiceInstance si = list.get(0);
        //通过ServiceInstance获取到他的url和端口号,这些信息都在nacos中注册过了
        //如果使用了ribbon,这个就只能使用服务的名字了
//        String url = "http://"+si.getHost()+":"+si.getPort()+
//                "/api/v1/video/find_by_id?videoId="+videoId;
//        System.out.println(url);
        Video video = restTemplate.getForObject("http://wpb-video-service/api/v1/video/find_by_id?videoId="+videoId,Video.class);
        videoOrder.setVideoTitle(video.getTitle());
        videoOrder.setVideoId(video.getId());
        videoOrder.setServerInfo(video.getServeInfo());
        return videoOrder;
    }
}

Ribbon不规范,风格不统一,维护性比较差

新的负载均衡组件Feign

不用像Ribbon中通过封装HTTP请求报文的方式调用 Feign默认集成了Ribbon
Nacos支持Feign,可以直接集成实现负载均衡的效果

  1. 加入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 在每个启动类上加上注解
    @EnableFeignClients
  2. 在Order模块里service里添加

@FeignClient(value = "wpb-video-service")
public interface VideoService {

    @GetMapping("/api/v1/video/find_by_id")
    Video findById(@RequestParam("videoId") int videoId);
    @PostMapping("/api/v1/video/save")
    int save(@RequestBody Video video);

}

然后就可以在Order模块中的controlle里直接调用了,就像调用自己的service方法一样

个人qq:835493858 有事联系我
原文地址:https://www.cnblogs.com/wpbing/p/14326959.html