day10【微服务调用】

01-SpringCloud相关概念介绍

1、微服务的由来

微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一套小服务来开发单个应用的方式途径,每个服务运行在自己的进程中,并使用轻量级机制通信,通常是HTTP API,这些服务基于业务能力构建,并能够通过自动化部署机制来独立部署,这些服务使用不同的编程语言实现,以及不同数据存储技术,并保持最低限度的集中式管理。

2、为什么需要微服务

在传统的IT行业软件大多都是各种独立系统的堆砌,这些系统的问题总结来说就是扩展性差,可靠性不高,维护成本高。到后面引入了SOA服务化,但是,由于 SOA 早期均使用了总线模式,这种总线模式是与某种技术栈强绑定的,比如:J2EE。这导致很多企业的遗留系统很难对接,切换时间太长,成本太高,新系统稳定性的收敛也需要一些时间。

3、微服务与单体架构区别

(1)单体架构所有的模块全都耦合在一块,代码量大,维护困难。

         微服务每个模块就相当于一个单独的项目,代码量明显减少,遇到问题也相对来说比较好解决。

(2)单体架构所有的模块都共用一个数据库,存储方式比较单一。

         微服务每个模块都可以使用不同的存储方式(比如有的用redis,有的用mysql等),数据库也是单个模块对应自己的数据库。

(3)单体架构所有的模块开发所使用的技术一样。

        微服务每个模块都可以使用不同的开发技术,开发模式更灵活。 

4、微服务本质

(1)微服务,关键其实不仅仅是微服务本身,而是系统要提供一套基础的架构,这种架构使得微服务可以独立的部署、运行、升级,不仅如此,这个系统架构还让微服务与微服务之间在结构上“松耦合”,而在功能上则表现为一个统一的整体。这种所谓的“统一的整体”表现出来的是统一风格的界面,统一的权限管理,统一的安全策略,统一的上线过程,统一的日志和审计方法,统一的调度方式,统一的访问入口等等。

(2)微服务的目的是有效的拆分应用,实现敏捷开发和部署 。

(3)微服务提倡的理念团队间应该是 inter-operate, not integrate 。inter-operate是定义好系统的边界和接口,在一个团队内全栈,让团队自治,原因就是因为如果团队按照这样的方式组建,将沟通的成本维持在系统内部,每个子系统就会更加内聚,彼此的依赖耦合能变弱,跨系统的沟通成本也就能降低。

5、什么样的项目适合微服务

        微服务可以按照业务功能本身的独立性来划分,如果系统提供的业务是非常底层的,如:操作系统内核、存储系统、网络系统、数据库系统等等,这类系统都偏底层,功能和功能之间有着紧密的配合关系,如果强制拆分为较小的服务单元,会让集成工作量急剧上升,并且这种人为的切割无法带来业务上的真正的隔离,所以无法做到独立部署和运行,也就不适合做成微服务了。

6、微服务开发框架

目前微服务的开发框架,最常用的有以下四个:

    Spring Cloud:http://projects.spring.io/spring-cloud(现在非常流行的微服务架构)

    Dubbo:http://dubbo.io

    Dropwizard:http://www.dropwizard.io (关注单个微服务的开发)

    Consul、etcd&etc.(微服务的模块)

7、什么是Spring Cloud

        Spring Cloud是一系列框架的集合。它利用Spring Boot的开发便利性简化了分布式系统基础设施的开发,如服务发现、服务注册、配置中心、消息总线、负载均衡、 熔断器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过SpringBoot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

8、Spring Cloud和Spring Boot是什么关系

        Spring Boot 是 Spring 的一套快速配置脚手架,可以基于Spring Boot 快速开发单个微服务,Spring Cloud是一个基于Spring Boot实现的开发工具;Spring Boot专注于快速、方便集成的单个微服务个体,Spring Cloud关注全局的服务治理框架; Spring Boot使用了默认大于配置的理念,很多集成方案已经帮你选择好了,能不配置就不配置,Spring Cloud很大的一部分是基于Spring Boot来实现,必须基于Spring Boot开发。可以单独使用Spring Boot开发项目,但是Spring Cloud离不开 Spring Boot。

9、Spring Cloud相关基础服务组件

        服务发现——Netflix Eureka(Nacos)

        服务调用——Netflix Feign 

        熔断器——Netflix Hystrix 

        服务网关——Spring Cloud  GateWay

        分布式配置——Spring Cloud Config(Nacos)

        消息总线 —— Spring Cloud Bus(Nacos)

10、Spring Cloud的版本

Spring Cloud并没有熟悉的数字版本号,而是对应一个开发代号。

        开发代号看似没有什么规律,但实际上首字母是有顺序的,比如:Dalston版本,我们可以简称 D 版本,对应的 Edgware 版本我们可以简称 E 版本。

小版本

Spring Cloud 小版本分为:

SNAPSHOT: 快照版本,随时可能修改

M: MileStone,M1表示第1个里程碑版本,一般同时标注PRE,表示预览版版。

SR: Service Release,SR1表示第1个正式版本,一般同时标注GA:(GenerallyAvailable),表示稳定版本



02-服务发现-搭建Nacos服务

一、Nacos

1、基本概念

(1)Nacos 是阿里巴巴推出来的一个新开源项目,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。

(2)常见的注册中心:

        1. Eureka(原生,2.0遇到性能瓶颈,停止维护

        2. Zookeeper(支持,专业的独立产品。例如:dubbo)

        3. Consul(原生,GO语言开发)

        4. Nacos

        相对于 Spring Cloud Eureka 来说,Nacos 更强大。Nacos = Spring Cloud Eureka + Spring Cloud Config

        Nacos 可以与 Spring, Spring Boot, Spring Cloud 集成,并能代替 Spring Cloud Eureka, Spring Cloud Config

        - 通过 Nacos Server 和 spring-cloud-starter-alibaba-nacos-discovery 实现服务的注册与发现。

(3)Nacos是以服务为主要服务对象的中间件,Nacos支持所有主流的服务发现、配置和管理。

Nacos主要提供以下四大功能:

1. 服务发现和服务健康监测

2. 动态配置服务

3. 动态DNS服务

4. 服务及其元数据管理

(4)Nacos结构图

2、Nacos下载和安装

(1)下载地址和版本

下载地址:https://github.com/alibaba/nacos/releases

下载版本:nacos-server-1.1.4.tar.gz或nacos-server-1.1.4.zip,解压任意目录即可

(2)启动nacos服务

- Linux/Unix/Mac

启动命令(standalone代表着单机模式运行,非集群模式)

启动命令:sh startup.sh -m standalone


- Windows

启动命令:cmd startup.cmd 或者双击startup.cmd运行文件。

访问:http://localhost:8848/nacos

用户名密码:nacos/nacos

二、服务注册(service_edu为例)

把service-edu微服务注册到注册中心中。

1、在service模块配置pom

配置Nacos客户端的pom依赖

        <!--服务注册-->

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

        </dependency>

2、添加服务配置信息

配置application.properties,在客户端微服务中添加注册Nacos服务的配置信息

service-edu模块:

# nacos服务地址

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

3、添加Nacos客户端注解

service-edu模块:在客户端微服务启动类中添加注解

@EnableDiscoveryClient

4、启动客户端微服务

启动注册中心

启动已注册的微服务,可以在Nacos服务列表中看到被注册的微服务

        service-vod步骤相同。

        如果service_oss没有注册到注册中心中,启动时会报错(no server available),这是因为我们引入了服务注册依赖,启动时会找Nacos注册中心,但是因为我们没有做配置所以找不到。后面这些都需要在注册中心进行注册


03-服务调用-Feign

一、Feign

1、基本概念

    Feign是Netflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。

    Feign支持多种注解,例如Feign自带的注解或者JAX-RS注解等。

    Spring Cloud对Feign进行了增强,使Feign支持了Spring MVC注解,并整合了Ribbon和Eureka,从而让Feign的使用更加方便。

    Spring Cloud Feign是基于Netflix feign实现,整合了Spring Cloud Ribbon和Spring Cloud Hystrix,除了提供这两者的强大功能外,还提供了一种声明式的Web服务客户端定义的方式。

    Spring Cloud Feign帮助我们定义和实现依赖服务接口的定义。在Spring Cloud feign的实现下,只需要创建一个接口并用注解方式配置它,即可完成服务提供方的接口绑定,简化了在使用Spring Cloud Ribbon时自行封装服务调用客户端的开发量。

二、实现服务调用

前提条件:把互相调用服务在Nacos进行注册

1、需求

        删除课时的同时删除云端视频。

    通过service_edu模块调用service_vod中删除视频的方法(微服务)。

2、在service模块添加pom依赖

        <!--服务调用-->

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-openfeign</artifactId>

        </dependency

3、在调用端的启动类添加注解

调用端:我们需要实现service_edu(调用端,消费者)调用service_vod(被调用端,生产者)

@EnableFeignClients

4、创建包和接口

在调用端service_edu中创建client包,然后创建VodClient接口:

@FeignClient注解用于指定从哪个服务中调用功能 ,名称与被调用的服务名保持一致。

@GetMapping注解用于对被调用的微服务进行地址映射。

@PathVariable注解一定要指定参数名称,否则出错

@Component注解防止,在其他位置注入CodClient时idea报错

@FeignClient("service-vod")

@Component

public interface VodClient {

    //根据视频id删除阿里云视频

    //复制被调用者的方法,并把路径写完全

    @DeleteMapping("/eduvod/video/removeAlyVideo/{id}")

    public R removeAlyVideo(@PathVariable("id") String id);

}

5、调用微服务

在调用端中调用client中的方法

    //删除小节

    //TODO 后面这个方法需要完善:删除小节的时候,同时把里面视频删除

    @DeleteMapping("deleteVideo/{id}")

    public R deleteVideo(@PathVariable String id){

        //根据小节id获取视频id,调用方法实现视频删除

        EduVideo eduVideo = eduVideoService.getById(id);

        String videoSourceId = eduVideo.getVideoSourceId();

        //判断小节里面是否有视频id

        if (!StringUtils.isEmpty(videoSourceId)){

            //根据视频id,远程调用实现视频删除

            //需要注入VodClient,才可以使用service_vod中删除视频的方法

            vodClient.removeAlyVideo(videoSourceId);

        }

        //删除小节

        eduVideoService.removeById(id);

        return R.ok();

    }

6、测试

启动相关微服务

测试删除课时的功能:删除小节,数据库和阿里云视频都被删除。



04-完善删除课程业务

    需求:删除课程的同时删除云端视频

一、vod服务

1、web层接口

controller:VodController.java

    //批量删除视频

    //@RequestParam("videoIdList")表示参数的名称是videoIdList

    @DeleteMapping("delete-batch")

    public R removeAlyVideoList(@RequestParam("videoIdList") List videoIdList){

        vodService.removeMoreAlyVideo(videoIdList);

        return R.ok();

    }

2、业务

业务接口:VideoService.java

void removeMoreAlyVideo(List videoIdList);

业务实现:VideoServiceImpl.java

    @Override

    public void removeMoreAlyVideo(List videoIdList) {

        try {

            //初始化对象

            DefaultAcsClient client = InitObjectV.initVodClient(ConstantPropertiesUtil.ACCESS_KEY_ID,ConstantPropertiesUtil.ACCESS_KEY_SECRET);

            //创建删除视频request对象

            //一次只能批量删20个

            DeleteVideoRequest request = new DeleteVideoRequest();

            //videoIdList值转换为1,2,3

            String join = StringUtils.join(videoIdList.toArray(), ",");

            //向request设置视频id

            //传递id的格式:1,2,3

            request.setVideoIds(join);

            //调用初始化对象的方法实现删除

            client.getAcsResponse(request);

        } catch (ClientException e) {

            e.printStackTrace();

            throw new GuliException(20001,"删除视频失败");

        }

    }

3、Swagger测试

输入多个id,每个一行


二、edu服务

在service-edu调用service- vod接口实现删除多个视频的功能

(1)VodClient:定义服务名字,调用方法

1、client

VodClient.java

//批量删除视频

    //@RequestParam("videoIdList")表示参数的名称是videoIdList

    @DeleteMapping("/eduvod/video/delete-batch")

    public R removeAlyVideoList(@RequestParam("videoIdList") List<String> videoIdList);

2、业务

EduCourseControllerl.java:

EduCourseServiceImpll.java:

EduVideoServiceImpl.java

@Service

public class EduVideoServiceImpl extends ServiceImpl<EduVideoMapper, EduVideo> implements EduVideoService {

    @Autowired

    private VodClient vodClient;


    // 1 根据课程id删除小节

    //TODO 删除小节,删除对应视频文件

    @Override

    public boolean removeVideoByCourseId(String id) {

        //1 根据课程id查询课程所有的视频id

        QueryWrapper<EduVideo> eduVideoQueryWrapper = new QueryWrapper<>();

        eduVideoQueryWrapper.eq("course_id",id);

        //查询指定的列

        eduVideoQueryWrapper.select("video_source_id");

        List<EduVideo> eduVideoList = baseMapper.selectList(eduVideoQueryWrapper);


        // List<EduVideo> 变成 List<String>

        List<String> videoIds = new ArrayList<>();

        for (int i = 0; i < eduVideoList.size(); i++) {

            EduVideo eduVideo = eduVideoList.get(i);

            String videoSourceId = eduVideo.getVideoSourceId();

            if (!StringUtils.isEmpty(videoSourceId)){

                //放到videoIds里面

                videoIds.add(videoSourceId);

            }

        }

        //根据多个视频id删除多个视频

        if (videoIds.size()>0){

            vodClient.removeAlyVideoList(videoIds);

        }


        //删除小节

        //需要根据小节id进行删除,但是传递过来的是课程id,因此需要传递对象

        QueryWrapper<EduVideo> wrapper = new QueryWrapper<>();

        wrapper.eq("course_id",id);

        int delete = baseMapper.delete(wrapper);

        return delete > 0;

    }

}

测试:点击删除



05-熔断器

一、Hystrix基本概念

1、Spring Cloud调用接口过程

Spring Cloud 在接口调用上,大致会经过如下几个组件配合:

Feign ----->Hystrix —>Ribbon —>Http Client(apache http components 或者 Okhttp) 具体交互流程上,如下图所示:

(1)接口化请求调用当调用被@FeignClient注解修饰的接口时,在框架内部,将请求转换成Feign的请求实例feign.Request,交由Feign框架处理。

(2)Feign :转化请求Feign是一个http请求调用的轻量级框架,可以以Java接口注解的方式调用Http请求,封装了Http调用流程。

(3)Hystrix:熔断处理机制 Feign的调用关系,会被Hystrix代理拦截,对每一个Feign调用请求,Hystrix都会将其包装成HystrixCommand,参与Hystrix的流控和熔断规则。如果请求判断需要熔断,则Hystrix直接熔断,抛出异常或者使用FallbackFactory返回熔断Fallback结果;如果通过,则将调用请求传递给Ribbon组件。

(4)Ribbon:服务地址选择 当请求传递到Ribbon之后,Ribbon会根据自身维护的服务列表,根据服务的服务质量,如平均响应时间,Load等,结合特定的规则,从列表中挑选合适的服务实例,选择好机器之后,然后将机器实例的信息请求传递给Http Client客户端,HttpClient客户端来执行真正的Http接口调用;

(5)HttpClient :Http客户端,真正执行Http调用根据上层Ribbon传递过来的请求,已经指定了服务地址,则HttpClient开始执行真正的Http请求

2、Hystrix概念

Hystrix 是一个供分布式系统使用,提供延迟和容错功能,保证复杂的分布系统在面临不可避免的失败时,仍能有其弹性。

比如系统中有很多服务,当某些服务不稳定的时候,使用这些服务的用户线程将会阻塞,如果没有隔离机制,系统随时就有可能会挂掉,从而带来很大的风险。SpringCloud使用Hystrix组件提供断路器、资源隔离与自我修复功能。下图表示服务B触发了断路器,阻止了级联失败。

二、feign结合Hystrix使用

改造service-edu模块

1、在service的pom中添加依赖

     <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>

        </dependency>

        <!--hystrix依赖,主要是用  @HystrixCommand -->

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>

        </dependency>

        <!--服务注册-->

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>

        </dependency>

        <!--服务调用-->

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-starter-openfeign</artifactId>

        </dependency>

2、在service-edu配置文件中添加hystrix配置

#开启熔断机制

feign.hystrix.enabled=true

# 设置hystrix超时时间,默认1000ms

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000

3、在service-edu的client包里面创建熔断器的实现类

@Component

public class VodFileDegradeFeignClient implements VodClient{

    //出错之后执行

    @Override

    public R removeAlyVideo(String id) {

        return R.error().message("删除视频出错了");

    }

    @Override

    public R removeAlyVideoList(List<String> videoIdList) {

        return R.error().message("删除多个视频出错了");

    }

}

4、修改VodClient接口的注解

@FeignClient(name = "service-vod",fallback = VodFileDegradeFeignClient.class)

@Component

public interface VodClient {

    //根据视频id删除阿里云视频

    //复制被调用者的方法,并把路径写完全

    @DeleteMapping("/eduvod/video/removeAlyVideo/{id}")

    public R removeAlyVideo(@PathVariable("id") String id);

    //批量删除视频

    //@RequestParam("videoIdList")表示参数的名称是videoIdList

    @DeleteMapping("/eduvod/video/delete-batch")

    public R removeAlyVideoList(@RequestParam("videoIdList") List<String> videoIdList);

}

5、测试熔断器效果

使用Debug设置断点:

创建小节,然后关闭vod:

        在操作的时候,得到视频id,然后使用远程调用vod中的方法根据id删除视频,但是由于vod服务器已经停止,这时就会执行熔断器处理(当出现问题,就会执行熔断器的实现类中的方法)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354