dubbo系列二:dubbo常用功能总结(3)
16. 本地伪装
本地伪装 通常用于服务降级,比如某验权服务,当服务提供方全部挂掉后,客户端不抛出异常,而是通过Mock数据返回授权失败。
在spring配置文件中按以下方式配置:
<dubbo:service interface="com.foo.BarService" mock="com.foo.BarServiceMock" />
1)Mock是Stub的一个子集,便于服务提供方在客户端执行容错逻辑,因经常需要在出现RpcException(比如网络失败,超时等)时进行容错,而在出现业务异常(比如登录用户名密码错误)时不需要容错,如果用Stub,可能就需要捕获并依赖RpcException类,而用Mock就可以不依赖RpcException,因为它的约定就是只有出现RpcException时才执行。
2)在interface旁放一个Mock实现,它实现BarService接口,并有一个无参构造函数
在生产者dubbo-provider-web和消费者dubbo-consumer-web分别新建一个接口
package com.study.mock; /** * * @Description: 本地伪装接口 * @author leeSmall * @date 2018年10月25日 * */ public interface MockService { String mock(String param); }
在生产者dubbo-provider-web新建MockService接口的实现类
package com.study.mock; /** * * @Description: 本地伪装接口实现类 * @author leeSmall * @date 2018年10月25日 * */ public class MockServiceImpl implements MockService { public String mock(String param) { System.out.println("provider MockServiceImpl mock"); return "provider MockServiceImpl mock"; } }
在生产者dubbo-provider-web的applicationProvider.xml配置本地伪装接口
<!--本地伪装begin --> <bean id="mockServiceImpl" class="com.study.mock.MockServiceImpl"/> <dubbo:service interface="com.study.mock.MockService" ref="mockServiceImpl"/> <!--本地伪装end -->
在消费者dubbo-consumer-web创建本地伪装代理实例
package com.study.mock; /** * * @Description: 本地伪装代理实例 * @author leeSmall * @date 2018年10月25日 * */ public class LocalMockProxyService implements MockService { public String mock(String arg0) { System.out.println("local mock 做一下容错处理,这个就是服务降级"); return "local mock 做一下容错处理,这个就是服务降级"; } }
在消费者dubbo-consumer-web的applicationConsumer.xml配置调用的本地伪装接口和本地伪装代理实例
<!--本地伪装begin --> <dubbo:reference id="mockServiceImpl" interface="com.study.mock.MockService" mock="com.study.mock.LocalMockProxyService"/> <!--本地伪装end -->
在消费者dubbo-consumer-web的CommonController.java里面创建本地伪装接口测试代码
//本地伪装begin @Autowired MockService mock; @RequestMapping("/mock") public @ResponseBody String mock() { String result = mock.mock("vvvv"); System.out.println(result); return "OK"; } //本地伪装end
在浏览器输入地址http://localhost:8081/dubbo-consumer-web/common/mock访问查看效果:
生产者:
消费者:
停掉生产者,再次在浏览器访问查看效果:
消费者:
17. 延迟暴露
延迟到Spring初始化完成后,再暴露服务,规避spring的加载死锁问题
生产者单个服务接口配置:
<dubbo:service delay="-1" />
生产者全局服务接口配置:
<dubbo:provider deplay=”-1” />
源码实现方式:ApplicationListener<ContextRefreshEvent> 监控ContextRefreshEvent事件
18. 并发控制
服务端配置:
限制com.foo.BarService的每个方法,服务器端并发执行(或占用线程池线程数)不能超过10个:
<dubbo:service interface="com.foo.BarService" executes="10" />
限制com.foo.BarService的sayHello方法,服务器端并发执行(或占用线程池线程数)不能超过10个:
<dubbo:service interface="com.foo.BarService"> <dubbo:method name="sayHello" executes="10" /> </dubbo:service>
客户端配置:
限制com.foo.BarService的每个方法,每个客户端并发执行(或占用连接的请求数)不能超过10个:
<dubbo:service interface="com.foo.BarService" actives="10" /> <dubbo:reference interface="com.foo.BarService" actives="10" />
限制com.foo.BarService的sayHello方法,每个客户端并发执行(或占用连接的请求数)不能超过10个:
<dubbo:service interface="com.foo.BarService"> <dubbo:method name="sayHello" actives="10" /> </dubbo:service> <dubbo:reference interface="com.foo.BarService"> <dubbo:method name="sayHello" actives="10" /> </dubbo:service>
如果<dubbo:service>和<dubbo:reference>都配了actives, <dubbo:reference>优先
19. 连接控制
服务端连接控制
限制服务器端接受的连接不能超过10个
<dubbo:provider protocol="dubbo" accepts="10" /> <dubbo:protocol name="dubbo" accepts="10" />
客户端连接控制
限制客户端服务使用连接不能超过10个
<dubbo:reference interface="com.foo.BarService" connections="10" /> <dubbo:service interface="com.foo.BarService" connections="10" />
延迟连接
延迟连接用于减少长连接数。当有调用发起时,再创建长连接。
<dubbo:protocol name="dubbo" lazy="true" />
注意:该配置只对使用长连接的dubbo协议生效。
粘滞连接
粘滞连接用于有状态服务,尽可能让客户端总是向同一提供者发起调用,除非该提供者挂了,再连另一台。
粘滞连接将自动开启延迟连接,以减少长连接数。
<dubbo:protocol name="dubbo" sticky="true" />
20. 令牌验证
通过令牌验证在注册中心控制权限,以决定要不要下发令牌给消费者,可以防止消费者绕过注册中心访问提供者,另外通过注册中心可灵活改变授权方式,而不需修改或升级提供者
可以在生产者(客户端不需要配置token,只需要从注册中心获取服务时获取即可)全局设置开启令牌验证:
<!--随机token令牌,使用UUID生成--> <dubbo:provider interface="com.foo.BarService" token="true" /> <!--固定token令牌,相当于密码--> <dubbo:provider interface="com.foo.BarService" token="123456" />
21. 路由规则
路由规则:决定一次dubbo服务调用的目标服务器,分为条件路由规则和脚本路由规则,并且支持可扩展。
向注册中心写入路由规则的操作通常由监控中心或治理中心的页面完成
示例:
registry.register(URL.valueOf("condition://0.0.0.0/com.foo.BarService?category=routers
&dynamic=false&rule=" + URL.encode("host = 10.20.153.10 => host = 10.20.153.11") + "));
示例属性说明:
condition:// 表示路由规则的类型,支持条件路由规则和脚本路由规则,可扩展,必填。
0.0.0.0 表示对所有 IP 地址生效,如果只想对某个 IP 的生效,请填入具体 IP,必填。
com.foo.BarService 表示只对指定服务生效,必填。
category=routers 表示该数据为动态配置类型,必填。
dynamic=false 表示该数据为持久数据,当注册方退出时,数据依然保存在注册中心,必填。
enabled=true 覆盖规则是否生效,可不填,缺省生效。
force=false 当路由结果为空时,是否强制执行,如果不强制执行,路由结果为空的路由规则将自动失效,可不填,缺省为 flase 。
runtime=false 是否在每次调用时执行路由规则,否则只在提供者地址列表变更时预先执行并缓存结果,调用时直接从缓存中获取路由结果。如果用了参数路由,必须设为true ,需要注意设置会影响调用的性能,可不填,缺省为flase。
priority=1 路由规则的优先级,用于排序,优先级越大越靠前执行,可不填,缺省为0。
rule=URL.encode("host = 10.20.153.10 => host = 10.20.153.11") 表示路由规则的内容,必填。
条件路由规则
基于条件表达式的路由规则
示例:host = 10.20.153.10 => host = 10.20.153.11
示例说明:
=> 之前的为消费者匹配条件,所有参数和消费者的 URL 进行对比,当消费者满足匹配
条件时,对该消费者执行后面的过滤规则。
=> 之后为提供者地址列表的过滤条件,所有参数和提供者的 URL 进行对比,消费者最终只拿到过滤后的地址列表。
如果匹配条件为空,表示对所有消费方应用,如:=> host != 10.20.153.11
如果过滤条件为空,表示禁止访问,如:host = 10.20.153.10 =>
表达式参数支持:
服务调用信息,如:method,argument等,暂不支持参数路由
URL本身的字段,如:protocol,host,port等,以及URL上的所有参数,如:application,organization等
条件支持:
等号 = 表示"匹配",如: host = 10.20.153.10
不等号 != 表示"不匹配",如: host != 10.20.153.10
值支持:
以逗号 , 分隔多个值,如: host != 10.20.153.10,10.20.153.11
以星号 * 结尾,表示通配,如: host != 10.20.*
以美元符 $ 开头,表示引用消费者参数,如: host = $host
白名单:
host != 10.20.153.10,10.20.153.11 =>
黑名单:
host = 10.20.153.10,10.20.153.11 =>
读写分离:
method = find*,list*,get*,is* => host = 172.22.3.94,172.22.3.95,172.22.3.96
method != find*,list*,get*,is* => host = 172.22.3.97,172.22.3.98
前后台分离:
application = bops => host = 172.22.3.91,172.22.3.92,172.22.3.93
application != bops => host = 172.22.3.94,172.22.3.95,172.22.3.96
22. 服务降级
可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
向注册中心写入动态配置覆盖规则:
mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
还可以改为 mock=fail:return+null 表示消费方对该服务的方法调用在失败后,再返回null值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。