dubbo的应用场景与高级特性之高级用法篇腾讯云开发者社区

关闭某个服务的启动时检查(没有提供者时报错):

关闭所有服务的启动时检查(没有提供者时报错):

关闭注册中心启动时检查(注册订阅失败时报错):

通过dubbo.properties

dubbo.reference.com.foo.BarService.check=falsedubbo.consumer.check=falsedubbo.registry.check=false通过-D参数

java-Ddubbo.reference.com.foo.BarService.check=falsejava-Ddubbo.consumer.check=falsejava-Ddubbo.registry.check=false6.2直连提供者Dubbo中点对点的直连方式

在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直连方式,将以服务接口为单位,忽略注册中心的提供者列表,A接口配置点对点,不影响B接口从注册中心获取列表。

配置:

6.3集群容错集群调用失败时,Dubbo提供的容错方案

在集群调用失败时,Dubbo提供了多种容错方案,缺省为failover重试。

各节点关系:

FailoverCluster

失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过retries="2"来设置重试次数(不含第一次)。该配置为缺省配置

FailfastCluster

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

FailsafeCluster

失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

FailbackCluster

失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

ForkingCluster

并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过forks="2"来设置最大并行数。

BroadcastCluster

广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

AvailableCluster

调用目前可用的实例(只调用一个),如果当前没有可用的实例,则抛出异常。通常用于不需要负载均衡的场景。

@reference(cluster="broadcast",parameters={"broadcast.fail.percent","20"})6.4负载均衡Dubbo提供的集群负载均衡策略

在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用。

具体实现上,Dubbo提供的是客户端负载均衡,即由Consumer通过负载均衡算法得出需要将请求提交到哪个Provider实例。

负载均衡策略

目前Dubbo内置了如下负载均衡算法,用户可直接配置使用:

算法

特性

备注

RandomLoadBalance

加权随机

默认算法,默认权重相同

RoundRobinLoadBalance

加权轮询

借鉴于Nginx的平滑加权轮询算法,默认权重相同

LeastActiveLoadBalance

最少活跃优先+加权随机

背后是能者多劳的思想,最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差;使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

ShortestResponseLoadBalance

最短响应优先+加权随机

ConsistentHashLoadBalance

一致性Hash

一致性Hash,相同参数的请求总是发到同一提供者。当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

6.5服务分组使用服务分组区分服务接口的不同实现

当一个接口有多种实现时,可以用group区分。

服务端

@DubboService(group="groupImpl1")publicclassGroupImpl1implementsGroup{@OverridepublicStringdoSomething(Strings){System.out.println("===========GroupImpl1.doSomething");return"GroupImpl1.doSomething";}}代码语言:javascript复制@DubboService(group="groupImpl2")publicclassGroupImpl2implementsGroup{@OverridepublicStringdoSomething(Strings){System.out.println("===========GroupImpl2.doSomething");return"GroupImpl2.doSomething";}}消费端

@DubboReference(check=false,group="groupImpl1"/*,parameters={"merger","true"}*/)Groupgroup;6.6分组聚合通过分组对结果进行聚合并返回聚合后的结果

通过分组对结果进行聚合并返回聚合后的结果,比如菜单服务,用group区分同一接口的多种实现,现在消费方需从每种group中调用一次并返回结果,对结果进行合并之后返回,这样就可以实现聚合菜单项。

生产者配置:

@DubboService(group="groupImpl1")publicclassGroupImpl1implementsGroup{@OverridepublicStringdoSomething(Strings){System.out.println("===========GroupImpl1.doSomething");return"GroupImpl1.doSomething";}}@DubboService(group="groupImpl2")publicclassGroupImpl2implementsGroup{@OverridepublicStringdoSomething(Strings){System.out.println("===========GroupImpl2.doSomething");return"GroupImpl2.doSomething";}}消费者配置:

@DubboReference(check=false,group="*",parameters={"merger","true"})Groupgroup;SPI文件配置在resources下创建META-INF文件夹并在其下面创建dubbo文件夹,然后在dubbo文件夹下面创建org.apache.dubbo.rpc.cluster.Merger文件,在该文件下写好Merger的实现类,如:

publicclassStringMergerimplementsMerger{//定义了所有group实现类的返回值的合并规则@OverridepublicStringmerge(String...strings){if(strings.length==0){returnnull;}StringBuilderbuilder=newStringBuilder();for(Stringstring:strings){if(string!=null){builder.append(string).append("-");}}returnbuilder.toString();}}6.7多版本在Dubbo中为同一个服务配置多个版本

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

可以按照以下的步骤进行版本迁移:

@DubboService(version="1.0.0")publicclassVersionServiceImplimplementsVersionService{@OverridepublicStringversion(Strings){System.out.println("========VersionServiceImpl.1.0.0");return"========VersionServiceImpl.1.0.0";}}@DubboService(version="1.0.1")publicclassVersionServiceImpl1implementsVersionService{@OverridepublicStringversion(Strings){System.out.println("========VersionServiceImpl1.1.0.1");return"========VersionServiceImpl1.1.0.1";}}消费者配置:

@DubboReference(check=false,version="1.0.0")VersionServiceversionService;6.8参数验证在Dubbo中进行参数验证

Maven依赖

javax.validationvalidation-api1.0.0.GAorg.hibernatehibernate-validator4.2.0.Final参数验证类:

publicclassValidationParamterimplementsSerializable{privatestaticfinallongserialVersionUID=32544321432L;@NotNull@Size(min=2,max=20)privateStringname;@Min(18L)@Max(100L)privateintage;@PastprivateDateloginDate;@FutureprivateDateexpiryDate;}生产者:

@DubboServicepublicclassValidationServiceImplimplementsValidationService{@Overridepublicvoidsave(ValidationParamtervalidationParamter){System.out.println("========ValidationServiceImpl.save");}@Overridepublicvoidupdate(ValidationParamtervalidationParamter){System.out.println("========ValidationServiceImpl.update");}@Overridepublicvoiddelete(longl,Strings){System.out.println("========ValidationServiceImpl.delete");}}消费者:

@DubboReference(check=false,validation="true")ValidationServicevalidationService;@Testpublicvoidvalidation(){ValidationParamterparamter=newValidationParamter();paramter.setName("Jack");paramter.setAge(98);paramter.setLoginDate(newDate(System.currentTimeMillis()-10000000));paramter.setExpiryDate(newDate(System.currentTimeMillis()+10000000));validationService.save(paramter);}6.9使用泛化调用选讲做测试的,没有使用场景

实现一个通用的服务测试框架,可通过GenericService调用所有服务实现

泛化接口调用方式主要用于客户端没有API接口及模型类元的情况,参数及返回值中的所有POJO均用Map表示,通常用于框架集成,比如:实现一个通用的服务测试框架,可通过GenericService调用所有服务实现。

消费者:

@Testpublicvoidusegeneric(){ApplicationConfigapplicationConfig=newApplicationConfig();applicationConfig.setName("dubbo_consumer");RegistryConfigregistryConfig=newRegistryConfig();registryConfig.setAddress("zookeeper://192.168.67.139:2184");ReferenceConfigreferenceConfig=newReferenceConfig<>();referenceConfig.setApplication(applicationConfig);referenceConfig.setInterface("com.xiangxue.jack.service.UserService");//这个是使用泛化调用referenceConfig.setGeneric(true);GenericServicegenericService=referenceConfig.get();Objectresult=genericService.$invoke("queryUser",newString[]{"java.lang.String"},newObject[]{"Jack"});System.out.println(result);}6.10参数回调通过参数回调从服务器端调用客户端逻辑

服务接口示例:

publicinterfaceCallbackService{voidaddListener(Stringvar1,CallbackListenervar2);}CallbackListener.java

publicinterfaceCallbackListener{voidchanged(Stringmsg);}生产者:

@DubboService(methods={@Method(name="addListener",arguments={@Argument(index=1,callback=true)})})publicclassCallbackServiceImplimplementsCallbackService{@OverridepublicvoidaddListener(Strings,CallbackListenercallbackListener){//这里就是回调客户端的方法callbackListener.changed(getChanged(s));}privateStringgetChanged(Stringkey){return"Changed:"+newSimpleDateFormat("yyyy-MM-dd:mm:ss").format(newDate());}}消费者:

@DubboReference(check=false)CallbackServicecallbackService;callbackService.addListener("jack",newCallbackListener(){publicvoidchanged(Stringarg0){System.out.println("=====================callbackresult:"+arg0);}});6.11本地存根在Dubbo中利用本地存根在客户端执行部分逻辑

远程服务后,客户端通常只剩下接口,而实现全在服务器端,但提供方有些时候想在客户端也执行部分逻辑,比如:做ThreadLocal缓存,提前验证参数,调用失败后伪造容错数据等等,此时就需要在API中带上Stub,客户端生成Proxy实例,会把Proxy通过构造函数传给Stub1,然后把Stub暴露给用户,Stub可以决定要不要去调Proxy。

生产者:

@DubboServicepublicclassStubServiceImplimplementsStubService{@OverridepublicStringstub(Strings){System.out.println("==========本地存根业务逻辑=========");returns;}}消费者:

@DubboReference(check=false,stub="cn.enjoy.stub.LocalStubProxy")StubServicestubService;@Testpublicvoidstub(){System.out.println(stubService.stub("jingtian"));}代理层:

如何在Dubbo中利用本地伪装实现服务降级

生成者:

@DubboServicepublicclassMockServiceImplimplementsMockService{@OverridepublicStringmock(Strings){System.out.println("=======mockservice的业务处理=======");try{Thread.sleep(1000000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("=======mockservice的业务处理完成=======");return"MockServiceImpl.mock";}@OverridepublicStringqueryArea(Strings){returns;}@OverridepublicStringqueryUser(Strings){returns;}}消费者:

//这两种方式会走rpc远程调用fail--会走远程服务@DubboReference(check=false,mock="true")//@DubboReference(check=false,mock="cn.enjoy.mock.LocalMockService")//不走服务直接降级force--是不会走远程服务的,强制降级..这种方式是用dubbo-admin去配置它,服务治理的方式//@DubboReference(check=false,mock="force:returnjack")MockServicemockService;@Testpublicvoidmock(){System.out.println(mockService.mock("wy"));}代码语言:javascript复制/**MockServiceMock**1、接口名+"Mock"*2、mock逻辑必须定义在接口的包下面*/publicclassMockServiceMockimplementsMockService{@OverridepublicStringmock(Strings){System.out.println(this.getClass().getName()+"--mock");returns;}@OverridepublicStringqueryArea(Strings){System.out.println(this.getClass().getName()+"--queryArea");returns;}@OverridepublicStringqueryUser(Strings){System.out.println(this.getClass().getName()+"--queryUser");returns;}}6.13异步调用在Dubbo中发起异步调用

从2.7.0开始,Dubbo的所有异步编程接口开始以CompletableFuture为基础

基于NIO的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。

代码案例

publicinterfaceAsyncService{StringasynctoDo(Stringvar1);}@DubboServicepublicclassAsyncServiceImplimplementsAsyncService{@OverridepublicStringasynctoDo(Strings){for(inti=0;i<10;i++){System.out.println("===============AsyncServiceImpl.asynctoDo");try{Thread.sleep(100);}catch(InterruptedExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}}return"hello,"+s;}}消费者:

@DubboReference(check=false,timeout=1000000000,methods={@Method(name="asynctoDo",async=true)})AsyncServiceasyncService;@Testpublicvoidasync()throwsInterruptedException{Stringaa=asyncService.asynctoDo("aa");System.out.println("main=="+aa);System.out.println("并行调用其他接口====");try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}//需要拿到异步调用的返回结果CompletableFutureresultFuture=RpcContext.getContext().getCompletableFuture();resultFuture.whenComplete((retValue,exception)->{if(exception==null){System.out.println("正常返回=="+retValue);}else{exception.printStackTrace();}});Thread.currentThread().join();}6.14异步执行Dubbo服务提供方的异步执行

Provider端异步执行将阻塞的业务从Dubbo内部线程池切换到业务自定义线程,避免Dubbo线程池的过度占用,有助于避免不同服务间的互相影响。异步执行无异于节省资源或提升RPC响应性能,因为如果业务执行需要阻塞,则始终还是要有线程来负责执行。

注意:

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

publicinterfaceAsyncService{CompletableFuturedoOne(Stringvar1);}@OverridepublicCompletableFuturedoOne(Strings){returnCompletableFuture.supplyAsync(()->{try{Thread.sleep(5000);}catch(InterruptedExceptione){e.printStackTrace();}return"doOne--OK";});}消费者:

@TestpublicvoidasyncDoone()throwsExecutionException,InterruptedException{CompletableFuturejingtian=asyncService.doOne("jingtian");jingtian.whenComplete((retValue,exception)->{if(exception==null){System.out.println(retValue);}else{exception.printStackTrace();}});Thread.currentThread().join();}6.15本地调用在Dubbo中进行本地调用

本地调用使用了injvm协议,是一个伪协议,它不开启端口,不发起远程调用,只在JVM内直接关联,但执行Dubbo的Filter链。

本地调用,调用的就是本地工程的接口实例

示例:

@DubboReference(check=false,injvm=true)StudentServicestudentService;@TestpublicvoidinJvm()throwsInterruptedException{System.out.println(studentService.find("xx"));}6.16粘滞连接为有状态服务配置粘滞连接

粘滞连接用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非该提供者挂了,再连另一台。

粘滞连接将自动开启延迟连接,以减少长连接数。

sticky=true

@DubboReference(check=false,protocol="dubbo",retries=3,timeout=1000000000,cluster="failover",loadbalance="random",sticky=true,methods={@Method(name="doKill",isReturn=false)}/*,url="dubbo://localhost:20880"*/)UserServiceuserService;6.17Protobuf使用IDL定义服务

当前Dubbo的服务定义和具体的编程语言绑定,没有提供一种语言中立的服务描述格式,比如Java就是定义Interface接口,到了其他语言又得重新以另外的格式定义一遍。2.7.5版本通过支持ProtobufIDL实现了语言中立的服务定义。

1、maven插件支持

在dubbo-p工程的src/main下面创建proto文件夹在里面定义LoginService.proto文件,文件内容如下:

生成文件如下:

4、把生成的文件移到响应的service目录下

生产者代码:

@DubboService@Slf4jpublicclassLoginServiceImplimplementsLoginService{@OverridepublicLoginReplylogin(LoginRequestrequest){log.info("Hello"+request.getUsername()+",requestfromconsumer:"+RpcContext.getContext().getRemoteAddress());returnLoginReply.newBuilder().setMessage("Hello"+request.getUsername()+",responsefromprovider:"+RpcContext.getContext().getLocalAddress()).build();}@OverridepublicCompletableFutureloginAsync(LoginRequestrequest){returnnull;}}生产者配置:

必须要加上序列化的配置属性,在dubbo-provider.properties中配置

dubbo.service.cn.enjoy.service.login.LoginService.serialization=protobuf消费者:

消费者的1,2,3,4步骤是相同的

消费者代码:

@Testpublicvoidprotobuf()throwsIOException{LoginRequestrequest=LoginRequest.newBuilder().setUsername("jingtian").setPassword("123").build();LoginReplyreply=loginService.login(request);System.out.println(reply.getMessage());}6.18主机绑定在Dubbo中绑定主机名

缺省主机IP查找顺序:

主机配置

注册的地址如果获取不正确,比如需要注册公网地址,可以:

1、可以在/etc/hosts中加入:机器名公网IP,比如:

test1205.182.23.2012、在dubbo.xml中加入主机地址的配置:

3、或在dubbo.properties中加入主机地址的配置:

dubbo.protocol.host=205.182.23.201端口配置

协议

端口

dubbo

20880

rmi

1099

80

hessian

webservice

memcached

11211

redis

6379

可以按照下面的方式配置端口:

1、在dubbo.xml中加入主机地址的配置:

2、或在dubbo.properties中加入主机地址的配置:

dubbo.protocol.dubbo.port=208806.19主机配置自定义Dubbo服务对外暴露的主机地址

背景

在Dubbo中,Provider启动时主要做两个事情,一是启动server,二是向注册中心注册服务。启动server时需要绑定socket,向注册中心注册服务时也需要发送socket唯一标识服务地址。

dubbo中不设置host时默认host是什么

一般的dubbo协议配置如下:

......可以看到,只配置了端口号,没有配置host,此时设置的host又是什么呢

查看代码发现,在org.apache.dubbo.config.ServiceConfig#findConfigedHosts()中,通过InetAddress.getLocalHost().getHostAddress()获取默认host。其返回值如下:

那在dubbo中如何指定服务的socket

除此之外,可以通过dubbo.protocol或dubbo.provider的host属性对host进行配置,支持IP地址和域名,如下:

......在使用docker时,有时需要设置端口映射,此时,启动server时绑定的socket和向注册中心注册的socket使用不同的端口号,此时又该如何设置?

见dubbo通过环境变量设置host

有些部署场景需要动态指定服务注册的地址,如dockerbridge网络模式下要指定注册宿主机ip以实现外网通信。dubbo提供了两对启动阶段的系统属性,用于设置对外通信的ip、port地址。

以上四个配置项均为可选项,如不配置dubbo会自动获取ip与端口,请根据具体的部署场景灵活选择配置。dubbo支持多协议,如果一个应用同时暴露多个不同协议服务,且需要为每个服务单独指定ip或port,请分别在以上属性前加协议前缀。如:

PORT_TO_REGISTRY或IP_TO_REGISTRY不会用作默认PORT_TO_BIND或IP_TO_BIND,但是反过来是成立的如设置PORT_TO_REGISTRY=20881IP_TO_REGISTRY=30.5.97.6,则PORT_TO_BINDIP_TO_BIND不受影响如果设置PORT_TO_BIND=20881IP_TO_BIND=30.5.97.6,则默认PORT_TO_REGISTRY=20881IP_TO_REGISTRY=30.5.97.6

总结

减少注册中心上服务的注册数据

Dubboprovider中的服务配置项有接近30个配置项。排除注册中心服务治理需要之外,很大一部分配置项是provider自己使用,不需要透传给消费者。这部分数据不需要进入注册中心,而只需要以key-value形式持久化存储。

这些数据是以服务为维度注册进入注册中心,导致了数据量的膨胀,进而引发注册中心(如zookeeper)的网络开销增大,性能降低。

现有功能sample当前现状一个简单展示。通过这个展示,分析下为什么需要做简化配置。

参考sample子工程:dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-nosimple(跑sample前,先跑下ZKClean进行配置项清理)

dubbo-provider.xml配置

启动provider的main方法之后,查看zookeeper的叶子节点(路径为:/dubbo/org.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService/providers目录下)的内容如下:

dubbo%3A%2F%2F30.5.124.158%3A20880%2Forg.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService%3Fanyhost%3Dtrue%26application%3Dsimplified-registry-xml-provider%26async%3Dtrue%26dubbo%3D2.0.2%26**executes**%3D4500%26generic%3Dfalse%26group%3Ddubbo-simple%26interface%3Dorg.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService%26methods%3DsayHello%26**owner**%3Dvict%26pid%3D2767%26**retries**%3D7%26revision%3D1.2.3%26side%3Dprovider%26**timeout**%3D5300%26timestamp%3D1542361152795%26valid%3Dtrue%26version%3D1.2.3从加粗字体中能看到有:executes,retries,owner,timeout。但是这些字段不是每个都需要传递给dubboops或者dubboconsumer。同样的,consumer也有这个问题,可以在例子中启动Consumer的main方法进行查看。

设计目标和宗旨

期望简化进入注册中心的provider和consumer配置数量。期望将部分配置项以其他形式存储。这些配置项需要满足:不在服务调用链路上,同时这些配置项不在注册中心的核心链路上(服务查询,服务列表)。

配置

简化注册中心的配置,只在2.7之后的版本中进行支持。开启provider或者consumer简化配置之后,默认保留的配置项如下:

ConstantKey

Key

remark

APPLICATION_KEY

application

CODEC_KEY

codec

EXCHANGER_KEY

exchanger

SERIALIZATION_KEY

serialization

CLUSTER_KEY

cluster

CONNECTIONS_KEY

connections

DEPRECATED_KEY

deprecated

GROUP_KEY

group

LOADBALANCE_KEY

loadbalance

MOCK_KEY

mock

PATH_KEY

path

TIMEOUT_KEY

timeout

TOKEN_KEY

token

VERSION_KEY

version

WARMUP_KEY

warmup

WEIGHT_KEY

weight

TIMESTAMP_KEY

timestamp

DUBBO_VERSION_KEY

SPECIFICATION_VERSION_KEY

specVersion

新增,用于表述dubbo版本,如2.7.0

consumer:

ConstantKey表示来自于类org.apache.dubbo.common.Constants的字段。

下面介绍几种常用的使用方式。所有的sample,都可以查看sample-2.7

方式1.配置dubbo.properties

sample在dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-xml工程下(跑sample前,先跑下ZKClean进行配置项清理)

dubbo.properties

dubbo.registry.simplified=truedubbo.registry.extra-keys=retries,owner怎么去验证呢?

provider端验证

provider端配置

dubbo%3A%2F%2F30.5.124.149%3A20880%2Forg.apache.dubbo.samples.simplified.registry.nosimple.api.DemoService%3Fapplication%3Dsimplified-registry-xml-provider%26dubbo%3D2.0.2%26group%3Ddubbo-simple%26**owner**%3Dvict%26**retries**%3D7%26**timeout**%3D5300%26timestamp%3D1542594503305%26version%3D1.2.3和上面的现有功能sample进行对比,上面的sample中,executes,retries,owner,timeout四个配置项都进入了注册中心。但是本实例不是:

总结:timeout,retries,owner进入了注册中心,而executes没有进入。

consumer端配置

sample在dubbo-samples-simplified-registry/dubbo-samples-simplified-registry-annotation工程下(跑sample前,先跑下ZKClean进行配置项清理)

Provider配置

privide端bean配置:

//等同于dubbo.properties配置,用@Bean形式进行配置@BeanpublicRegistryConfigregistryConfig(){RegistryConfigregistryConfig=newRegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");registryConfig.setSimplified(true);registryConfig.setExtraKeys("retries,owner");returnregistryConfig;}//暴露服务@Service(version="1.1.8",group="d-test",executes=4500,retries=7,owner="victanno",timeout=5300)publicclassAnnotationServiceImplimplementsAnnotationService{@OverridepublicStringsayHello(Stringname){System.out.println("asyncproviderreceived:"+name);return"annotation:hello,"+name;}}和上面sample中的dubbo.properties的效果是一致的。结果如下:

Consumer配置

consumer端bean配置:

@BeanpublicRegistryConfigregistryConfig(){RegistryConfigregistryConfig=newRegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");registryConfig.setSimplified(true);returnregistryConfig;}消费服务:

@Component("annotationAction")publicclassAnnotationAction{@Reference(version="1.1.8",group="d-test",owner="vvvanno",retries=4,actives=6,timeout=4500)privateAnnotationServiceannotationService;publicStringdoSayHello(Stringname){returnannotationService.sayHello(name);}}和上面sample中consumer端的配置是一样的。结果如下:

如果一个应用中既有provider又有consumer,那么配置需要合并成:

@BeanpublicRegistryConfigregistryConfig(){RegistryConfigregistryConfig=newRegistryConfig();registryConfig.setAddress("zookeeper://127.0.0.1:2181");registryConfig.setSimplified(true);//只对provider生效registryConfig.setExtraKeys("retries,owner");returnregistryConfig;}后续规划

本版本还保留了大量的配置项,接下来的版本中,会逐渐删除所有的配置项。

通过上下文存放当前调用过程中所需的环境信息

上下文中存放的是当前调用过程中所需的环境信息。所有配置信息都将转换为URL的参数,参见schema配置参考手册中的对应URL参数一列。

RpcContext是一个ThreadLocal的临时状态记录器,当接收到RPC请求,或发起RPC请求时,RpcContext的状态都会变化。比如:A调B,B再调C,则B机器上,在B调C之前,RpcContext记录的是A调B的信息,在B调C之后,RpcContext记录的是B调C的信息。

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

publicclassXxxServiceImplimplementsXxxService{publicvoidxxx(){//本端是否为提供端,这里会返回truebooleanisProviderSide=RpcContext.getContext().isProviderSide();//获取调用方IP地址StringclientIP=RpcContext.getContext().getRemoteHost();//获取当前服务配置信息,所有配置信息都将转换为URL的参数Stringapplication=RpcContext.getContext().getUrl().getParameter("application");//注意:每发起RPC调用,上下文状态会变化yyyService.yyy();//此时本端变成消费端,这里会返回falsebooleanisProviderSide=RpcContext.getContext().isProviderSide();}}6.22隐式参数通过Dubbo中的Attachment在服务消费方和提供方之间隐式传递参数

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

注意

path,group,version,dubbo,token,timeout几个key是保留字段,请使用其它值。

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