dubbo 项目环境组网方案

1 篇文章 0 订阅
1 篇文章 0 订阅

考虑到研发在项目开发中,因微服务化带来的依赖服务不稳定、联调不方便的问题,为减少开发过程中,因环境问题消耗的成本,现基于dubbo的源码的扩展,提供项目环境组网功能。

 

项目组网效果

 

部署说明

项目环境由本地机器启动的应用与开发环境的应用组成。

如上图案例,当前开发的项目涉及变更应用有

  1. 用户A负责的service-A,service-B在本地机器启动
  2. 用户B负责的service-D,在本地机器启动。
  3. 用户B同时在本地启动XXX-web,作为项目环境组网的入口。

调用链路

示例中,APP/H5向后端发起一个请求,调用顺序为

APP/H5 => XXX-web => service-A => service-B => service-C => service-D

  1. 请求到达用户B机器的XXX-web
  2. XXX-web需要请求service-A服务,此服务同时存在用户A机器与开发环境,因为用户机器的的服务优先级高,所以请求到用户A机器service-A.
  3. service-A.需要请求service-B服务,此服务同时存在用户A机器与开发环境,因为用户机器的的服务优先级高,所以请求到用户A机器service-B.
  4. service-B.需要请求service-C服务,此服务同时仅存在开发环境,所以请求到开发环境的service-C
  5. service-C需要请求service-D服务,此服务同时存在用户B机器与开发环境,因为用户机器的的服务优先级高,所以请求到用户B机器service-D.

服务调用过程

服务调用时,可以简单分为两个阶段,

  1. 获取服务提供者列表
  2. 远程调用服务

下面分别分析。

获取服务提供者列表

远程调用服务

获取服务提供者列表时,既能获取到项目环境的服务提供者,也能获取到稳定环境的服务提供者。

远程调用服务时,

  1. 如果服务存在项目环境,则优先调用项目环境的服务,如项目环境服务未找到,则调用稳定环境的服务
  2. 服务请求从项目环境的服务A调到稳定服务B,当服务B需要调用服务的下一个服务C,
    1. 如果服务C在项目环境存在,则调用到项目环境的服务C
    2. 否则,调用到开发环境的服务C

分组特性

消费者的group设置为*时,有以下特点

  • 在查找服务提供者时,只需要匹配服务接口。
  • 在调用服务时,可以匹配所有group不为空的服务提供者。

dubbo分组特性,正好与我们的项目环境组网相同。

在要组网时,所有相关开发约定一个dubbo group(假定为dev1)。需要在本地启动的应用使用"dev1"作为服务group。

< dubbo:reference id="xxxService" check="false" timeout = "60000" version="1.0.0" interface="com.ryze.service.opt.api.service.XXXService" group="*" />

开发环境启动的服务,统一使用group为"*"

< dubbo:reference id="xxxService" check="false" timeout = "60000" version="1.0.0" interface="com. ryze.service.opt.api.service.XXXService" group="*" />

要实前面所述的“XXX-web需要请求service-A服务,此服务同时存在用户A机器与开发环境,因为用户机器的的服务优先级高,所以请求到用户A机器service-A.”。还需要一种机制,在调用服务时,对服务列表进行过滤。

当月group为"*"是,消费调用会进入到“org.apache.dubbo.rpc.cluster.support.MergeableCluster”

 

 

 

而MergeableCluster的doJoin方法返回”org.apache.dubbo.rpc.cluster.support.MergeableClusterInvoker"实例。

MergeableClusterInvoker的doInvoke(Invocation,List<Invoker<T>>,LoadBalance)方法的逻辑是,将集群中的调用结果聚合起来返回结果。

 这个功能有点鸡肋,我们一般用不到。但我们可以利用这里的调用链做我们服务提供者列表过滤功能。因为MergeableCluster方法是代码写死引用MergeableClusterInvoker的。

我们可以复用dubbo spi机制重写“mergeable”指向自定义的ProjectMergeableCluster,在ProjectMergeableCluster中,我们再直接引用片定义的“ProjectMergeableClusterInvoker”

 
package org.apache.dubbo.demo.consumer.comp;

import org.apache.dubbo.rpc.RpcException;

import org.apache.dubbo.rpc.cluster.Directory;

import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;

import org.apache.dubbo.rpc.cluster.support.wrapper.AbstractCluster;

public class ProjectMergeableCluster extends AbstractCluster {

public static final String NAME = "mergeable";

@Override

public <T> AbstractClusterInvoker<T> doJoin(Directory<T> directory) throws RpcException {

return new ProjectMergeableClusterInvoker<T>(directory);

}

}
package org.apache.dubbo.demo.consumer.comp;

import org.apache.dubbo.common.constants.CommonConstants;

import org.apache.dubbo.common.utils.CollectionUtils;

import org.apache.dubbo.common.utils.StringUtils;

import org.apache.dubbo.rpc.*;

import org.apache.dubbo.rpc.cluster.Directory;

import org.apache.dubbo.rpc.cluster.LoadBalance;

import org.apache.dubbo.rpc.cluster.support.MergeableClusterInvoker;

import java.util.List;

public class ProjectMergeableClusterInvoker<T> extends MergeableClusterInvoker<T> {

public ProjectMergeableClusterInvoker(Directory directory) {

super(directory);

}

@Override

protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {

List<Invoker<T>> availableInvokers = null;

String projectGroup = RpcContext.getContext().getAttachment("projectGroup");

if(StringUtils.isBlank(projectGroup)){

projectGroup = ProjectEnvUtils.getGroup();

}

if(!StringUtils.isBlank(projectGroup)){

for(Invoker<T> invoker: invokers){

if(projectGroup.equals(invoker.getUrl().getParameter(CommonConstants.GROUP_KEY))){

availableInvokers.add(invoker);

}

}

}

if(CollectionUtils.isEmpty(availableInvokers)){

availableInvokers = invokers;

}

return super.doInvoke(invocation, availableInvokers, loadbalance);

}

}

ProjectMergeableClusterInvoker继承了MergeableClusterInvoker,ProjectMergeableClusterInvoker的doInvoke方法中,先完成服务列表invokers的过滤,然后再调用父类MergeableClusterInvoker的doInvoke。

源码地址:https://gitee.com/raisewang/ryze-commons

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Dubbo是一个分布式服务框架,可以帮助我们快速构建高性能、可扩展的分布式应用。下面是一个简单的Dubbo项目搭建的步骤: 1. 创建Maven项目:首先,在你的IDE中创建一个新的Maven项目。 2. 添加Dubbo依赖:在项目的pom.xml文件中添加Dubbo的依赖。示例代码如下: ```xml <dependencies> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>2.7.12</version> </dependency> </dependencies> ``` 3. 配置Dubbo服务提供者:创建一个Java类作为Dubbo服务提供者,并在类上添加Dubbo的注解。示例代码如下: ```java import org.apache.dubbo.config.annotation.DubboService; @DubboService public class DemoServiceImpl implements DemoService { // 实现接口方法 } ``` 4. 配置Dubbo服务消费者:创建一个Java类作为Dubbo服务消费者,并在类上添加Dubbo的注解。示例代码如下: ```java import org.apache.dubbo.config.annotation.DubboReference; public class DemoConsumer { @DubboReference private DemoService demoService; // 调用远程服务方法 } ``` 5. 配置Dubbo注册中心:在项目的配置文件中配置Dubbo的注册中心,比如Zookeeper。示例配置如下: ```properties # dubbo.registry.address指定注册中心地址 dubbo.registry.address=zookeeper://127.0.0.1:2181 ``` 6. 运行项目:启动Dubbo服务提供者和消费者,通过Dubbo的注册中心进行服务的注册和发现。 以上是一个简单的Dubbo项目搭建的步骤,具体可以根据你的实际需求进行相应的配置和调整。希望对你有所帮助!如有更多问题,请继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值