SpringCloud渐进试分析汇总(一)

一、微服务直接调用

通过RestTemplate订单服务直接访问视频服务

1、在SpringBoot启动类中添加RestTemplate对象交给SpringBoot管理。

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

        SpringApplication.run(OrderApplication.class,args);
    }

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

}

2、在订单服务中,自动注RestTemplate对象,通过restTemplate.getForObject()方法远程调用视频服务。

Video video = restTemplate.getForObject("http://localhost:9000/api/v1/video/find_by_id?

存在问题:

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

二、解决上面问题:微服务应用和机器器越来越多,调用方需要知道接口的网络地址,不易维护。

解决方法:使用注册中心进行管理。

原理:

  • 服务注册:服务提供者provider,启动的时候向注册中心上报自己的网络信息
  • 服务发现:服务消费者consumer,启动的时候向注册中心上报自己的网络信息,拉取provider的相关网络信息
  • 核心:服务管理理,是有个服务注册表,心跳机制动态维护,服务实例在启动时注册到服务注册表,并在关闭时注销。

主流的注册中心:zookeeper、Eureka、consul、etcd、Nacos

1、nacos搭建安装

  • 解压安装包
  • 进入bin⽬目录
  • 启动 sh startup.sh -m standalone
  • 访问 localhost:8848/nacos
  • 默认账号密码 nacos/nacos

2、子服务pom文件添加nacos依赖

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

3、yml文件配置Nacos地址

spring:
    application:
        name: xdclass-video-service
    cloud:
        nacos:
        discovery:
        server-addr: 127.0.0.1:8848

4、SpringBoot启动类增加注解

        @EnableDiscoveryClient

5、子服务之间的调用(订单服务调用视频服务)

 @RequestMapping("/save")
    public VideoOrder save(int videoId){
        VideoOrder videoOrder = new VideoOrder();
        List<ServiceInstance> instances = discoveryClient.getInstances("xdclass-video-service");
        Video video = restTemplate.getForObject("http://"+instances.get(0).getHost()+":"+instances.get(0).getPort()+"/api/v1/video/find_by_id?videoId="+videoId, Video.class);        
        videoOrder.setCreateTime(new Date());
        videoOrder.setId(video.getId());
        videoOrder.setVideoId(video.getId());
        videoOrder.setVideoImg(video.getCoverImg());
        videoOrder.setVideoTitle(video.getTitle());
        videoOrder.setServerInfo(video.getServerInfo());
        return videoOrder;
    }

缺点:

  • 同一个服务多个节点,无法做到多种策略的负载均衡
  • 每个服务都需要拼接连接地址,不易维护、开发

三、解决上面问题:同一个服务多个节点,无法做到多种策略的负载均衡,每个服务都需要拼接连接地址,不易维护、开发。

解决方法:AlibabaCloud集成Ribbon实现负载均衡。

原理:

  • Ribbon 是一个客户端负载均衡工具,通过Spring Cloud封装,可以轻松和AlibabaCloud整合
  • 订单服务增加@LoadBalanced 注解

步骤:

1、Ribbon与RestTemplate结合,实现负载均衡

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

2、通过Ribbon负载均衡调用视频服务

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

通过视频服务在nacos注册是服务名称进行调用,Ribbon服务自动从nacos拉取对应服务列表,并进行负载均衡调用。

负载均衡策略略调整:

在spring boot 配置文件中添加如下配置

xdclass-video-service:
    ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
策略命令描述
RandomRule随机策略随机选择server
RoundRobinRule轮询策略按照顺序选择server(默认)
RetryRule重试策略当选择server不成功,短期内尝试选择一个可用的server
AvailabilityFilteringRule可用过滤略过滤掉⼀直失败并被标记
为circuit tripped的server,过滤掉那些⾼并发链接的server(activeconnections超过配置的阈值)
WeightedResponseTimeRule响应时间加权策略

根据server的响应时间分
配权重,以响应时间作为
权重,响应时间越短的服
务器被选中的概率越⼤,综合了各种因素,比如:网络,磁盘,io等,都直接影响响应时间

ZoneAvoidanceRule区域权重策略综合判断server所在区域
的性能,和server的可用性,轮询选择server

缺点:ribbon代码存在的问题:不规范,风格不统一,维护性比较差,需要拼接http请求

四、优化ribbon代码存在的问题:不规范,风格不统一,维护性比较差,需要拼接http请求

解决方法:通过Open-Feign使用Java接口注解的方式调用Http请求。

原理:

  • SpringCloud(Open-Feign)提供的伪http客户端(本质还是⽤用http),封装了了Http调用流程,更适合面向接口化,让用Java接口注解的方式调用Http请求.
  • 不用像Ribbon中通过封装HTTP请求报文的方式调用 ,Feign默认集成了了Ribbon

步骤:

1、spring boot pom文件中加入feign依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、配置注解

启动类增加@EnableFeignClients

3、增加一个接口,并添加@FeignClient注解

订单服务增加接⼝口,服务名称记得和nacos保持⼀一样
@FeignClient(name="xdclass-video-service")

4、编写GET请求实现方法,并添加@GetMapping注解

@GetMapping(value ="/api/v1/video/find_by_id")
Video findById(@RequestParam("videoId") int videoId);

5、编写POST请求实现方法,并添加@PostMapping注解

//订单服务这边
@PostMapping(value = "/api/v1/video/save")
Video saveVideo(@RequestBody Video video);

@PostMapping("/api/v1/video/save1")
public Object save(@RequestBody Video video){
    System.out.println(video.getTitle());
    return video;
}

Ribbon和feign两个的区别和选择:

  • 选择feign默认集成了ribbon写起来更加思路清晰和方便
  • 采用注解方式进行配置,配置熔断等方式方便

五、解决高并发下的微服务容错方案,解决微服务容错问题

解决方法:通过Sentinel服务设置限流、熔断、降级、隔离策略提供微服务容错能力。

优势:

  • 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性
  • 丰富的应用场景:消息削峰填谷、集群流量控制、实时熔断下游不可用应用等
  • 完备的实时监控:Sentinel 同时提供实时的监控功能
  • 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合

步骤:

1、微服务引入Sentinel依赖

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

2、Sentinel控制台搭建

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentineldashboard-1.8.0.jar

3、多个微服务接入Sentinel配置

spring:
    cloud:
        sentinel:
        transport:
        dashboard: 127.0.0.1:8080
        port: 9999

4、配置限流策略

5、Sentinel自定义异常-整合Open-Feign

【新版】实现BlockExceptionHandler并且重写handle方法

public class XdclassUrlBlockHandler implements BlockExceptionHandler {
@Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        //降级业务处理理

        Map<String,Object> backMap=new HashMap<>();
        if (e instanceof FlowException){
            backMap.put("code",-1);
            backMap.put("msg","限流-异常啦");
        }else if (e instanceof DegradeException){
            backMap.put("code",-2);
            backMap.put("msg","降级-异常啦");
        }else if (e instanceof ParamFlowException){
            backMap.put("code",-3);
            backMap.put("msg","热点-异常啦");
        }else if (e instanceof SystemBlockException){
            backMap.put("code",-4);
            backMap.put("msg","系统规则-异常啦");
        }else if (e instanceof AuthorityException){
            backMap.put("code",-5);
            backMap.put("msg","认证-异常啦");
        }
        // 设置返回json数据
        httpServletResponse.setStatus(200);
        httpServletResponse.setHeader("content-Type","application/json;charset=UTF-8");
        httpServletResponse.getWriter().write(JSON.toJSONString(backMap));
    }
}

 6、开启Feign对Sentinel的支持

feign:
    sentinel:
        enabled: true

7、创建容错类, 实现对应的服务接口

@Service
public class VideoServiceFallback implements VideoService {
    @Override
    public Video findById(int videoId) {
        Video video = new Video();
        video.setTitle("熔断降级数据");
        return video;
    }
    @Override
    public Video saveVideo(Video video) {
        return null;
    }
}

8、配置feign容错类,添加注解

@FeignClient(value = "xdclass-video-service",fallback = VideoServiceFallback.class)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值