Dubbo学习圣经:从入门到精通Dubbo3.0+SpringCloudAlibaba微服务基础框架

丰富的线上&线下活动,深入探索云世界

做任务,得社区积分和周边

最真实的开发者用云体验

让每位学生受益于普惠算力

让创作激发创新

资深技术专家手把手带教

遇见技术追梦人

技术交流,直击现场

海量开发者使用工具、手册,免费下载

极速、全面、稳定、安全的开源镜像

开发手册、白皮书、案例集等实战精华

为开发者定制的Chrome浏览器插件

在40岁老架构师尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,并且拿了很多大厂offer。

其中SpringCloud工业级底座,是大家的面试核心,面试重点。比如小伙伴在面试网易的时候,就遇到以下面试题:

dubbo和springcloud区别是什么?dubbo3.0和springcloud如何整合?

dubbo3.0和springcloudGateway如何整合?

小伙伴由于之前没有系统的去梳理和总结,所以支支吾吾的说了几句,面试官不满意,面试挂了。

所以,尼恩给大家做一下系统化、体系化的梳理,联合社群小伙伴,来一个Sa-Token学习圣经:从入门到精通Sa-Token学习圣经。

特别说明的是,本文属于尼恩团队从0到1大实战:穿透SpringCloud工业级底座工程(一共包括15大圣经的)其中之一。

15大圣经,使得大家内力猛增,可以充分展示一下大家雄厚的“技术肌肉”,让面试官爱到“不能自已、口水直流”,然后实现”offer直提”。

工业级脚手架实现的包括的15大学习圣经,目录如下:

本文,就是Dubbo学习圣经。这个版本,稍后会录制视频.

录完之后,Dubbo学习圣经正式版本会有更新,最新版本找尼恩获取。

ApacheDubbo是一款RPC服务开发框架,用于解决微服务架构下的服务治理与通信问题,官方提供了Java、Golang等多语言SDK实现。使用Dubbo开发的微服务原生具备相互之间的远程地址发现与通信能力,利用Dubbo提供的丰富服务治理特性,可以实现诸如服务发现、负载均衡、流量调度等服务治理诉求。2022年阿里巴巴将其内部HSF系统与开源社区Dubbo相融合,与社区一同推出了云原生时代的Dubbo3架构,截止2022年双十一结束,Dubbo3已经在阿里巴巴内部广泛落地,实现了老版本HSF2框架升级,包括电商核心、阿里云等核心系统已经全面运行在Dubbo3之上。

以上是Dubbo的工作原理图,从抽象架构上分为两层:服务治理抽象控制面和Dubbo数据面。

RPC(RemoteProcedureCall)—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。现在业界有很多开源的优秀RPC框架,例如SpringCloud、Dubbo、Thrift等。RPC这个概念术语在上世纪80年代由BruceJayNelson提出。这里我们追溯下当初开发RPC的原动机是什么?在Nelson的论文“ImplementingRemoteProcedureCalls”中他提到了几点:

通俗一点说,就是一般程序员对于本地的过程调用很熟悉,那么我们把RPC作成和本地调用完全类似,那么就更容易被接受,使用起来毫无障碍。Nelson的论文发表于30年前,其观点今天看来确实高瞻远瞩,今天我们使用的RPC框架基本就是按这个目标来实现的。

RPC调用分以下两种:

异步和同步的区分在于是否等待服务端执行完成并返回结果。

官网说dubbo3.3和springcloud可以互通,参考官方案例dubbo-samples-springcloud

使用Dubbo最主要的原因是,Dubbo在通信性能、稳定性方面具有无可比拟的优势,非常适合构建近乎无限水平伸缩的微服务集群,这也是Dubbo从实践层面优于业界很多同类的产品的巨大优势。

Dubbo内置支持Dubbo2、Triple两款高性能通信协议。其中

在本任务中,将分为3个子模块进行独立开发,模拟生产环境下的部署架构。

./dubbo-samples/1-basic/dubbo-samples-spring-boot├──dubbo-samples-spring-boot-interface//共享API模块├──dubbo-samples-spring-boot-consumer//消费端模块└──dubbo-samples-spring-boot-provider//服务端模块如上所示,共有3个模块,其中interface模块被consumer和provider两个模块共同依赖,存储RPC通信使用的API接口。

生产环境参考高可用Zookeeper集群安装

启动一个服务消费者来调用服务提供者后,打印出的数据就是服务提供者处理之后返回的,标志着一次服务调用的成功。

org.apache.dubbodubbo-spring-boot-demo-interface${project.parent.version}org.apache.dubbodubbo-spring-boot-starterorg.apache.dubbodubbo-dependencies-zookeeper-curator5pomslf4j-reload4jorg.slf4jorg.springframework.bootspring-boot-starter在这份配置中,定义了dubbo和zookeeper(以及对应的连接器curator)的依赖。添加了上述的配置以后,可以通过IDEA的Maven-ReloadAllMavenProjects刷新依赖。

packageorg.apache.dubbo.springboot.demo;publicinterfaceDemoService{StringsayHello(Stringname);}在DemoService中,定义了sayHello这个方法。后续服务端发布的服务,消费端订阅的服务都是围绕着DemoService接口展开的。

packageorg.apache.dubbo.springboot.demo.provider;importorg.apache.dubbo.config.annotation.DubboService;importorg.apache.dubbo.springboot.demo.DemoService;@DubboServicepublicclassDemoServiceImplimplementsDemoService{@OverridepublicStringsayHello(Stringname){return"Hello"+name;}}在DemoServiceImpl中,实现了DemoService接口,对于sayHello方法返回Helloname。注:在DemoServiceImpl类中添加了@DubboService注解,通过这个配置可以基于SpringBoot去发布Dubbo服务。

dubbo:application:name:dubbo-springboot-demo-providerprotocol:name:dubboport:-1registry:address:zookeeper://${zookeeper.address:127.0.0.1}:2181在这个配置文件中,定义了Dubbo的应用名、Dubbo协议信息、Dubbo使用的注册中心地址。

dubbo:application:name:dubbo-springboot-demo-consumerprotocol:name:dubboport:-1registry:address:zookeeper://${zookeeper.address:127.0.0.1}:2181在这个配置文件中,定义了Dubbo的应用名、Dubbo协议信息、Dubbo使用的注册中心地址。

packageorg.apache.dubbo.springboot.demo.provider;importorg.apache.dubbo.config.spring.context.annotation.EnableDubbo;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@EnableDubbopublicclassProviderApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ProviderApplication.class,args);}}在这个启动类中,配置了一个ProviderApplication去读取我们前面第6步中定义的application.yml配置文件并启动应用。

packageorg.apache.dubbo.springboot.demo.consumer;importorg.apache.dubbo.config.spring.context.annotation.EnableDubbo;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@EnableDubbopublicclassConsumerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(ConsumerApplication.class,args);}}在这个启动类中,配置了一个ConsumerApplication去读取我们前面第7步中定义的application.yml配置文件并启动应用。

packageorg.apache.dubbo.springboot.demo.consumer;importjava.util.Date;importorg.apache.dubbo.config.annotation.DubboReference;importorg.apache.dubbo.springboot.demo.DemoService;importorg.springframework.boot.CommandLineRunner;importorg.springframework.stereotype.Component;@ComponentpublicclassTaskimplementsCommandLineRunner{@DubboReferenceprivateDemoServicedemoService;@Overridepublicvoidrun(String...args)throwsException{Stringresult=demoService.sayHello("world");System.out.println("Receiveresult======>"+result);newThread(()->{while(true){try{Thread.sleep(1000);System.out.println(newDate()+"Receiveresult======>"+demoService.sayHello("world"));}catch(InterruptedExceptione){e.printStackTrace();Thread.currentThread().interrupt();}}}).start();}}在Task类中,通过@DubboReference从Dubbo获取了一个RPC订阅,这个demoService可以像本地调用一样直接调用。在run方法中创建了一个线程进行调用。

生产环境下可以参考官方文档使用k8s和docker进行容器化安装,测试用环境,下载dubbo-admin-0.6.0,修改zookeeper配置,打包运行/dubbo-admin-server/target/dubbo-admin-server-0.6.0.jar即可

从注册中心视角来看,它负责以应用名(dubbo.application.name)对整个集群的实例地址进行聚合,每个对外提供服务的实例将自身的应用名、实例ip:port地址信息(通常还包含少量的实例元数据,如机器所在区域、环境等)注册到注册中心。

Dubbo2版本注册中心以服务粒度聚合实例地址,比应用粒度更细,也就意味着传输的数据量更大,因此在大规模集群下也遇到一些性能问题。

dubbo采用的是按需订阅每个消费服务的实例从注册中心订阅实例地址列表,相比于一些产品直接将注册中心的全量数据(应用+实例地址)加载到本地进程,Dubbo实现了按需精准订阅地址信息。比如一个消费者应用依赖app1、app2,则只会订阅app1、app2的地址列表更新,大幅减轻了冗余数据推送和解析的负担。

区别于其他很多微服务框架的是,Dubbo3的服务发现机制诞生于阿里巴巴超大规模微服务电商集群实践场景,因此,其在性能、可伸缩性、易用性等方面的表现大幅领先于业界大多数主流开源产品。是企业面向未来构建可伸缩的微服务集群的最佳选择。

Dubbo3采用应用级服务发现方案

结合以上两页对于Dubbo2接口级地址模型的分析,以及最开始的Dubbo基本原理图,我们可以得出这么几条结论:

为什么会出现这个问题?我们以一个具体provider示例进行展开,来尝试说明为何应用在接口级地址模型下容易遇到容量问题。青蓝色部分,假设这里有一个普通的DubboProvider应用,该应用内部定义有10个RPCService,应用被部署在100个机器实例上。这个应用在集群中产生的数据量将会是“Service数机器实例数”,也就是10100=1000条。数据被从两个维度放大:

在以下几种情况下会需要部署元数据中心:

比如:中文站有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心。

生产环境,参考文档部署高可用Nacos集群,测试环境部署本地单机版Nacos,步骤下

当Dubbo使用3.0.0及以上版本时,需要使用Nacos2.0.0及以上版本

2.0以上Nacos需要配置秘钥

com.alibaba.nacosnacos-client2.2.1增加Dubbo与Nacos依赖

#application.yml(SpringBoot)dubboregistryaddress:nacos://${nacos.address:localhost}:8848username=nacos&password=nacos3.4.4高级配置3.4.6注册接口级消费者Dubbo3.0.0版本以后,增加了是否注册消费者的参数,如果需要将消费者注册到nacos注册中心上,需要将参数(register-consumer-url)设置为true,默认是false。

#application.ymldubbo:registry:address:nacos://localhost:8848register-consumer-url=true或者

时,从0开始增加|simple||preserved.register.source|注册实例注册时服务框架类型(例如Dubbo,SpringCloud等)|空|

这些参数都可以类似namespace的方式通过通过参数扩展配置到Nacos,如

注:应用级服务发现的“服务名”为应用名Dubbo3默认采用“应用级服务发现+接口级服务发现”的双注册模式,因此会发现应用级服务(应用名)和接口级服务(接口名)同时出现在Nacos控制台,可以通过配置dubbo.registry.register-mode=instance/interface/all来改变注册行为。

有三种配置方式

参考示例/dubbo-samples-spring-boot在DubboSpringBoot开发中,你只需要增加几个注解,并配置application.properties或application.yml文件即可完成Dubbo服务定义:

dubbo:application:name:dubbo-springboot-demo-providerprotocol:name:dubboport:-1registry:id:zk-registryaddress:zookeeper://127.0.0.1:2181config-center:address:zookeeper://127.0.0.1:2181metadata-report:address:zookeeper://127.0.0.1:2181通过注解将service关联到上文定义的特定注册中心

@DubboService(registry="zk-registry")publicclassDemoServiceImplimplementsDemoService{}通过JavaConfig配置进行关联也是同样道理

@ConfigurationpublicclassProviderConfiguration{@BeanpublicServiceConfigdemoService(){ServiceConfigservice=newServiceConfig();service.setRegistry("zk-registry");returnservice;}}4.1.2常用注解定义好Dubbo服务接口后,提供服务接口的实现逻辑,并用@DubboService注解标记,就可以实现Dubbo的服务暴露

@DubboServicepublicclassDemoServiceImplimplementsDemoService{}如果要设置服务参数,@DubboService也提供了常用参数的设置方式。如果有更复杂的参数设置需求,则可以考虑使用其他设置方式

@DubboService(version="1.0.0",group="dev",timeout=5000)publicclassDemoServiceImplimplementsDemoService{}@EnableDubbo注解必须配置,否则将无法加载Dubbo注解定义的服务,@EnableDubbo可以定义在主类上

@SpringBootApplication@EnableDubbopublicclassProviderApplication{publicstaticvoidmain(String[]args)throwsException{SpringApplication.run(ProviderApplication.class,args);}}SpringBoot注解默认只会扫描main类所在的package,如果服务定义在其它package中,需要增加配置EnableDubbo(scanBasePackages={"org.apache.dubbo.springboot.demo.provider"})

虽然可以通过@DubboService和DubboReference调整配置参数(如下代码片段所示),但总体来说注解提供的配置项还是非常有限。在这种情况下,如果有更复杂的参数设置需求,可以使用JavaConfig或dubbo.properties两种方式。

@DubboService(version="1.0.0",group="dev",timeout=5000)@DubboReference(version="1.0.0",group="dev",timeout=5000)注意,JavaConfig是DubboService或DubboReference的替代方式,对于有复杂配置需求的服务建议使用这种方式。

dubbo.service.org.apache.dubbo.springboot.demo.DemoService.timeout=5000dubbo.service.org.apache.dubbo.springboot.demo.DemoService.parameters=[{myKey:myValue},{anotherKey:anotherValue}]dubbo.reference.org.apache.dubbo.springboot.demo.DemoService.timeout=60004.2XML配置参考/dubbo-samples-spring-xml案例

DemoService.java:

packageorg.apache.dubbo.demo;publicinterfaceDemoService{StringsayHello(Stringname);}DemoServiceImpl.java:

packageorg.apache.dubbo.demo.provider;importorg.apache.dubbo.demo.DemoService;publicclassDemoServiceImplimplementsDemoService{publicStringsayHello(Stringname){return"Hello"+name;}}

3.**加载Spring配置**```javapublicclassApplication{publicstaticvoidmain(String[]args)throwsInterruptedException{ClassPathXmlApplicationContextcontext=newClassPathXmlApplicationContext("spring/dubbo-demo-provider.xml");context.start();System.out.println("dubboservicestarted");//tohangupmainthreadnewCountDownLatch(1).await();}}4.2.2服务消费者

通过ServiceConfig暴露服务接口,发布服务接口到注册中心。

publicclassDemoProvider{publicstaticvoidmain(String[]args){

Dubbo异步调用分为Provider端异步调用和Consumer端异步调用。Provider端异步执行将阻塞的业务从Dubbo内部线程池切换到业务自定义线程,避免Dubbo线程池的过度占用,有助于避免不同服务间的互相影响。异步执行无异于节省资源或提升RPC响应性能。注意

Provider端异步执行和Consumer端异步调用是相互独立的,你可以任意正交组合两端配置

使用场景:

接口定义:

publicinterfaceAsyncService{/***同步调用方法*/Stringinvoke(Stringparam);/***异步调用方法*/CompletableFutureasyncInvoke(Stringparam);}服务实现:

@DubboServicepublicclassAsyncServiceImplimplementsAsyncService{@OverridepublicStringinvoke(Stringparam){try{longtime=ThreadLocalRandom.current().nextLong(1000);Thread.sleep(time);StringBuilders=newStringBuilder();s.append("AsyncServiceinvokeparam:").append(param).append(",sleep:").append(time);returns.toString();}catch(InterruptedExceptione){Thread.currentThread().interrupt();}returnnull;}@OverridepublicCompletableFutureasyncInvoke(Stringparam){//建议为supplyAsync提供自定义线程池returnCompletableFuture.supplyAsync(()->{try{//Dosomethinglongtime=ThreadLocalRandom.current().nextLong(1000);Thread.sleep(time);StringBuilders=newStringBuilder();s.append("AsyncServiceasyncInvokeparam:").append(param).append(",sleep:").append(time);returns.toString();}catch(InterruptedExceptione){Thread.currentThread().interrupt();}returnnull;});}}通过returnCompletableFuture.supplyAsync(),业务执行已从Dubbo线程切换到业务线程,避免了对Dubbo线程池的阻塞。

注:未测试,应该可以

Dubbo提供了一个类似Servlet3.0的异步接口AsyncContext,在没有CompletableFuture签名接口的情况下,也可以实现Provider端的异步执行。接口定义:

publicinterfaceAsyncService{StringsayHello(Stringname);}服务实现:

参考案例/version

Dubbo服务中,接口并不能唯一确定一个服务,只有接口+分组+版本号才能唯一确定一个服务。服务版本使用场景:

当一个接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。

老版本服务提供者配置

新版本服务提供者配置

5.2.2服务消费者老版本服务消费者配置

新版本服务消费者配置

如果不需要区分版本,可以按照以下的方式配置

5.3服务分组参考案例/group

同一个接口针对不同的业务场景、不同的使用需求或者不同的功能模块等场景,可使用服务分组来区分不同的实现方式。同时,这些不同实现所提供的服务是可并存的,也支持互相调用。当一个接口有多种实现时,可以用group区分。使用方式

使用@DubboService注解,添加group参数

使用@DubboReference注解,添加group参数

@DubboReference(group="demo")privateDemoServicedemoService;@DubboReference(group="demo2")privateDemoServicedemoService2;//group值为*,标识匹配任意服务分组@DubboReference(group="*")privateDemoServicedemoService2;5.3.3分组聚合参考案例/dubbo-samples-merge

全局链路追踪和隐藏参数。

服务消费方

//远程调用xxxService.xxx();//本端是否为消费端,这里会返回truebooleanisConsumerSide=RpcContext.getServiceContext().isConsumerSide();//获取最后一次调用的提供方IP地址StringserverIP=RpcContext.getServiceContext().getRemoteHost();//获取当前服务配置信息,所有配置信息都将转换为URL的参数Stringapplication=RpcContext.getServiceContext().getUrl().getParameter("application");//注意:每发起RPC调用,上下文状态会变化yyyService.yyy();服务提供方

publicclassXxxServiceImplimplementsXxxService{publicvoidxxx(){//本端是否为提供端,这里会返回truebooleanisProviderSide=RpcContext.getServiceContext().isProviderSide();//获取调用方IP地址StringclientIP=RpcContext.getServiceContext().getRemoteHost();//获取当前服务配置信息,所有配置信息都将转换为URL的参数Stringapplication=RpcContext.getServiceContext().getUrl().getParameter("application");//注意:每发起RPC调用,上下文状态会变化yyyService.yyy();//此时本端变成消费端,这里会返回falsebooleanisProviderSide=RpcContext.getServiceContext().isProviderSide();}}5.5调用链路传递隐式参数本小节参考案例/dubbo-samples-spring-boot-attachment

内部系统通过Dubbo调用时,traceId如何透传到服务提供方。

参考上一小节调用上下文使用

可以通过RpcContext上的setAttachment和getAttachment在服务消费方和提供方之间进行参数的隐式传递。

上下文信息是RPC框架很重要的一个功能,使用RpcContext可以为单次调用指定不同配置。如分布式链路追踪场景,其实现原理就是在全链路的上下文中维护一个traceId,Consumer和Provider通过传递traceId来连接一次RPC调用,分别上报日志后可以在追踪系统中串联并展示完整的调用流程。这样可以更方便地发现异常,定位问题。Dubbo中的RpcContext是一个ThreadLocal的临时状态记录器,当接收到RPC请求,或发起RPC请求时,RpcContext的状态都会变化。比如:A调B,B调C,则B机器上,在B调C之前,RpcContext记录的是A和B的信息,在B调C之后,RpcContext记录的是B和C的信息。在Dubbo3中,RpcContext被拆分为四大模块(ServerContext、ClientAttachment、ServerAttachment和ServiceContext)。它们分别承担了不同的职责:

setAttachment设置的KV对,在完成下面一次远程调用会被清空,即多次远程调用要多次设置。

@Activate(group={CommonConstants.CONSUMER})publicclassDubboConsumerFilterimplementsFilter{@OverridepublicResultinvoke(Invoker<>invoker,Invocationinvocation)throwsRpcException{invocation.setAttachment("demo","demo02");returninvoker.invoke(invocation);}}5.6本地存根和伪装本小节案例代码参考/mock-stub-demo

spring配置文件配置

提供Stub的实现

在SpringXML配置文件中按以下方式配置:

在工程中提供Mock实现[^2]:在interface旁放一个Mock实现,它实现BarService接口,并有一个无参构造函数。同时,如果没有在配置文件中显式指定Mock类的时候,那么需要保证Mock类的全限定类名是原全限定类名+Mock的形式,例如com.foo.BarServiceMock,否则将会Mock失败。

packagecom.foo;publicclassBarServiceMockimplementsBarService{publicStringsayHello(Stringname){//你可以伪造容错数据,此方法只在出现RpcException时被执行return"容错数据";}}使用return来返回一个字符串表示的对象,作为Mock的返回值。合法的字符串可以是:

举个例子,如果服务的消费方经常需要try-catch捕获异常,如:

publicclassDemoService{publicOfferfindOffer(StringofferId){Offeroffer=null;try{offer=offerService.findOffer(offerId);}catch(RpcExceptione){logger.error(e);}returnoffer;}}那么请考虑改为Mock实现,并在Mock实现中returnnull。如果只是想简单的忽略异常,在2.0.11以上版本可用:

使用throw来返回一个Exception对象,作为Mock的返回值。当调用出错时,抛出一个默认的RPCException:

当调用出错时,抛出指定的Exception:自定义异常必须拥有一个入参为String的构造函数,该构造函数将用于接受异常信息。

force:代表强制使用Mock行为,在这种情况下不会走远程调用。fail:与默认行为一致,只有当远程调用发生错误时才使用Mock行为。也就是说,配置的时候其实是可以不使用fail关键字的,直接使用throw或者return就可以了。force:和fail:都支持与throw或者return组合使用。强制返回指定值:

强制抛出指定异常:

调用失败时返回指定值:

调用失败时抛出异常

Mock可以在方法级别上指定,假定com.foo.BarService上有好几个方法,我们可以单独为sayHello()方法指定Mock行为。具体配置如下所示,在本例中,只要sayHello()被调用到时,强制返回“fake”:

5.7Filter通过自定义过滤器,可以对返回的结果进行统一的处理、验证等,减少对开发人员的打扰。案例常见过滤器对所有调用Provider服务的请求在返回的结果的后面统一打印日志在Provider中自定义一个Filter,在Filter中打印日志

4.**SPI配置**在`resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter`文件中添加如下配置:```propertiesappended=org.apache.dubbo.samples.extensibility.filter.provider.AppendedFilter在resources/application.properties文件中添加如下配置:

Triple协议是Dubbo3发布的面向云原生时代的通信协议,它基于HTTP/2并且完全兼容gRPC协议,原生支持Streaming通信语义,Triple可同时运行在HTTP/1和HTTP/2传输协议之上,让你可以直接使用curl、浏览器访问后端Dubbo服务。自Triple协议开始,Dubbo还支持基于ProtocolBuffers的服务定义与数据传输,但Triple实现并不绑定IDL,比如你可以直接使用JavaInterface定义和发布Triple服务。Triple具备更好的网关、代理穿透性,因此非常适合于跨网关、代理通信的部署架构,如服务网格等。Triple协议的核心特性如下:

在编程与通信模型上,Triple协议支持如下模式:

开发实践

Dubbo2协议是基于TCP传输层协议之上构建的一套RPC通信协议,由于其紧凑、灵活、高性能的特点,在Dubbo2时代取得了非常广泛的应用,是企业构建高性能、大规模微服务集群的关键通信方案。在云原生时代,我们更推荐使用通用性、穿透性更好的Triple协议。Dubbo2协议也内置HTTP支持,因此你可以使用curl在开发阶段快速验证或调试服务。

微服务领域常用的一种通信模式是HTTP+JSON,包括SpringCloud、Microprofile等一些主流的微服务框架都默认使用的这种通信模式,Dubbo同样提供了对基于HTTP的编程、通信模式的支持。

除了以上介绍的几种协议之外,你还可以将以下协议运行在Dubbo之上。对Dubbo而言,只需要修改一行简单的配置,就可以切换底层服务的通信协议,其他外围API和治理能力不受影响。

Triple是Dubbo3提出的基于HTTP的开放协议,旨在解决Dubbo2私有协议带来的互通性问题,Triple基于gRPC和gRPC-Web设计而来,保留了两者的优秀设计,Triple做到了完全兼容gRPC协议,并可同时运行在HTTP/1和HTTP/2之上。

总的来说,Unary模式适用于简单的请求-响应场景,而Streaming模式则更适合需要持续数据传输或大数据量传输的复杂场景。Dubbo3通过支持多种Streaming模式,提供了更大的灵活性来满足不同的应用需求

Stream是Dubbo3新提供的一种调用类型,在以下场景时建议使用流的方式:

Stream分为以下三种:

Triple协议的设计参考了gRPC、gRPC-Web、通用HTTP等多种协议模式,吸取每个协议各自的特性和优点,最终设计成为一个易于浏览器访问、完全兼容gRPC且支持Streaming通信的协议,Triple支持同时运行在HTTP/1、HTTP/2协议之上。Triple协议的设计目标如下:

当与ProtocolBuffers一起使用时(即使用IDL定义服务),Triple协议可支持unary、client-streaming、server-streaming和bi-streamingRPC通信模式,支持二进制Protobuf、JSON两种数据格式payload。Triple实现并不绑定ProtocolBuffers,比如你可以使用Java接口定义服务,Triple协议有对这种模式的扩展Content-type支持。

Unary是Triple协议的一部分,用于处理单次请求和响应的场景

以HTTP/1请求为例,目前HTTP/1协议仅支持UnaryRPC,支持使用application/proto和application/json编码类型,使用方式与REST风格请求保持一致,同时响应也包含常规的HTTP响应编码(如200OK)。

>POST/org.apache.dubbo.demo.GreetService/GreetHTTP/1.1>Host:127.0.0.1:30551>Content-Type:application/json>Rest-service-timeout:5000>>["Dubbo"]

Triple仅支持在HTTP/2上支持StreamingRPC。并且为了与gRPC协议保持兼容,Triple在HTTP/2协议实现上(包含StreamingRPC)保持与标准gRPC协议完全一致。Request

参考案例/triple

此模式下Triple使用方式与Dubbo2协议一样

optionjava_multiple_files=true;

packageorg.apache.dubbo.springboot.demo.provider;

messageGreeterRequest{stringname=1;}

messageGreeterReply{stringmessage=1;}

serviceGreeter{

rpcbiStream(streamGreeterRequest)returns(streamGreeterReply);

rpcserverStream(GreeterRequest)returns(streamGreeterReply);

}

微服务网关作为全局流量入口并不单单是一个反向路由,更多的是把各个边缘服务(Web层)的各种共性需求抽取出来放在一个公共的“服务”(网关)中实现,例如安全认证、权限控制、限流熔断、监控、跨域处理、聚合API文档等公共功能。

微服务网关是微服务架构中的一个关键的角色,用来保护、增强和控制对于微服务的访问。

下面是微服务网关的主要作用:

SpringCloudGateway是SpringCloud的一个全新项目,该项目是基于Spring5.0,SpringBoot2.0和ProjectReactor等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。

SpringCloudGateway作为SpringCloud生态系统中的网关,目标是替代Zuul,在SpringCloud2.0以上版本中,没有对新版本的Zuul2.0以上最新高性能版本进行集成,仍然还是使用的Zuul2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloudGateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

SpringCloudGateway的目标,不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

特别说明:SpringCloudGateway底层使用了高性能的通信框架Netty。Netty是高性能中间件的通讯底座,rocketmq、seata、nacos、sentinel、redission、dubbo等太多、太多的的大名鼎鼎的中间件,无一例外都是基于netty。

可以毫不夸张的说:netty是进入大厂、走向高端的必备技能。

要想深入了解springcloudgateway,最好是掌握netty编程。

在Dubbo框架体系,没有提供对前端的api网关,

Dubbo服务,要给前端调用有两种方式:

首先看问题。

web层一般是根据业务模块来切分的,用于聚合某个业务模块所依赖的各个service服务

一般来说,我们把上图中的web层全部整合在一起,成为一个BFF层。

这就变成了前面讲到的方式一:

方式一的问题:BFF层多了一层转发,多了一层网络传输,性能是比较低的。

SpringCloudGateway网关要整合dubbo的话需要解决以下问题:

SpringCloudGatewayDubbo基于SpringCloudAlibaba的SpringCloud集成Dubbo的方案之上开发,用于在SpringCloudGateway中直接调用Dubbo接口,可以减少使用Web接口来实现与gateway对接。

SpringCloudGatewayDubbo的架构图:

SpringCloudGateway网关直接调用Dubbo后无需WebApp进行中转

SpringCloudGateway+Dubbo的核心流程:

具体的内容,请参见尼恩团队的技术自由圈公号。

尼恩团队15大技术圣经,使得大家内力猛增,

可以充分展示一下大家雄厚的“技术肌肉”,让面试官爱到“不能自已、口水直流”,然后实现”offer直提”。

很多小伙伴刷完后,吊打面试官,大厂横着走。

在刷题过程中,如果有啥问题,大家可以来找40岁老架构师尼恩交流。

另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。

遇到职业难题,找老架构取经,可以省去太多的折腾,省去太多的弯路。

……完整版尼恩技术圣经PDF集群,请找尼恩领取

《尼恩架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

THE END
1.夏风“骗局再现”消费返现!有人上当被骗数万元在消费时避免被,短信等证据,月,消费返现,对于商家的保证内容要签署书面协议,则涉嫌诈骗。在多方寻找下2018个护肤项目,美容店宣称充值全返“消费日常项目”能够获得一定比例或金额的返还、是指消费者在完成购买行为后、张女士可以去法院起诉。 增加他们的购买意愿,如果商家签约收费的最终目的是为了卷钱跑路等“北京桦天https://bbs.9you.com/forum-113-10.html?modwap=viewthread&tid=596113
2.新情况!有人伪装消费者“反向骗”电商北京日报新情况!有人伪装消费者“反向骗”电商 北京日报 | 林靖 正文快照: 本报讯(记者 林靖)记者昨天从北京第一中级人民法院获悉,有犯罪分子利用电商平台在购物、退货及物流等方面的漏洞,伪装成消费者“反向”诈骗网络商家。法官表示,此类新型网购诈骗值得警惕。宋某冒用他人身份,在网购平台谎称购买笔记本电脑,并选择“到https://read.cnki.net/web/Newspaper/Article/BJRB202411120051.html
3.www.jxmzxx.com{$woaini}>www.jxmzxx.com{$woaini}通过近些年的宣传教育,广大消费者已经逐渐建立起了网购风险防范意识,但犯罪分子伪装成消费者“反向”诈骗网络商家的情况还不多见。该案给广大网络商家敲响了警钟。一方面,网络商家应当进一步提高对诈骗犯罪的警惕性,增强反诈意识,对于选择“到付”却又无理由拒收等情况特殊的大额订单要特别予以关注,及时跟进订单状态。另http://www.jxmzxx.com/appnews_20241118/74732745
4.771771威尼斯.cmapp大全771771威尼斯.cmapp版本合集首先,打开您的浏览器,输入771771威尼斯.cmApp的官方网址(http://anci.ykzhongji.com)。您可以通过搜索引擎搜索或直接输入网址来访问。 第二步:点击注册按钮 一旦进入771771威尼斯.cmApp官网,您会在页面上找到一个醒目的注册按钮。点击该按钮,您将被引导至注册页面。 http://anci.ykzhongji.com/
5.github.com/unzeo/fq[](https://i.postimg.cc/qMRLWY7V/125.png) + + + +关于培训机构诈骗内容 + +![](https://i.postimg.cc/PJFZfp9T/Snipaste-2019-05-由于消费者保护组织与监管机构缺位,商家违法成本过低 +①,走上维权之路的消费者很容易变成打官司的秋菊②,花费大量金钱及时间奔波,最终还是因为“耗不起”而https://github.com/unzeo/fq-book/commit/954bd824f2ff6cabc2c83bf048a244a81333ab33.diff
6.搭建网站实现DNS欺骗钓鱼网站是指欺骗用户的虚假网站。“钓鱼网站”的页面与真实网站界面基本一致,欺骗消费者或者窃取访问者提交的账号和密码信息。钓鱼网站一般只有一个或几个页面,和真实网站差别细微 [1]。钓鱼网站是互联网中最常碰到的一种诈骗方式,通常伪装成银行及电子商务、窃取用户提交的银行账号、密码等私密信息的网站。 https://blog.csdn.net/2301_77362941/article/details/136199435
7.专业术语具体包括:服务设施设备术语服务人员术语殡仪接待服务C. 自己和诈骗分子周旋,尝试要回资金 查看完整题目与答案 网购过程中,商家让王女士加好友私聊,纟合出了优惠的价格!以下哪个说法是对的?0 A. 网购脱离A. 刷单刷信誉本来就是违法行为,欺骗了真实的消费者,让他们对产品有虚假判断 B. 天上不会掉馅饼,哪有足不出户不需要付出劳动就把钱赚了的https://www.shuashuati.com/ti/082dbfef73164802992b03a8ed80921f.html?fm=bdbdsb55ee990fbe11a8a0ac7d0ab076347ec