简易Dubbo实现


随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,就需一个治理系统确保架构有条不紊的演进,Dubbo由此产生。

Dubbo 架构

在这里插入图片描述
节点角色说明

节点说明
Provider暴露服务的服务提供方
Consumer调用远程服务的服务消费方
Registry服务注册与发现的注册中心
Monitor统计服务的调用次数和调用时间的监控中心
Container服务运行器

调用关系说明

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

简易Dubbo实现

在这里插入图片描述

1. Dubbo API

新建一个maven项目,项目结构如下:
在这里插入图片描述

1.1 编写DTO
1.1.1 客户端到服务器的标准DTO

RPCCommonReqDTO

@Data
public class RPCCommonReqDTO implements Serializable {
    private static final long serialVersionUID = 1540605806624661461L;
    // 服务调用实现类全路径
    private String classPath;
    // 方法名称
    private String methodName;
    // 方法参数s
    private Object[] args;
}
1.1.2 其他DTO

UserDTO

@Data
public class UserDTO implements Serializable {
    private static final long serialVersionUID = 2320008609104776008L;
    private String id;
    private String name;
    private Integer age;
    private String sex;
}

OrgDto

@Data
public class OrgDto implements Serializable {
    private static final long serialVersionUID = -2463193363004747278L;
    private String id;
    private String parentId;
    private String name;
    private String code;
}
1.2 定义服务接口

OrgService

// 服务实现类全路径
@ImplAnnotion("com.lizq.api.impl.OrgServiceImpl")
public interface OrgService {
    /**
     * 添加组织
     * @param org
     * @return
     */
    OrgDto addOrg(OrgDto org);
}

UserService

@ImplAnnotion("com.lizq.api.impl.UserServiceImpl")
public interface UserService {

    /**
     * 添加用户
     * @param user
     * @return
     */
    UserDTO addUser(UserDTO user);
}
1.3 定义获取服务实现类全路径Annotion

@ImplAnnotion

/**
 * 用于标识该服务实现类全路径
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ImplAnnotion {
    String value();
}

执行 mvn clean install 将 rpc-api 打为 jar 包已供Provider、Consumer引用。

2. Provider

新建一个maven项目,项目结构如下
在这里插入图片描述
引入 rpc-api 依赖

2.1 编写服务接口实现类

编写服务接口实现类
UserServiceImpl

public class UserServiceImpl implements UserService {
    @Override
    public UserDTO addUser(UserDTO userDTO) {
        // TODO 参数验证、数据新增
        userDTO.setId(UUID.randomUUID().toString());
        return userDTO;
    }
}

OrgServiceImpl

public class OrgServiceImpl implements OrgService {
    @Override
    public OrgDto addOrg(OrgDto orgDto) {
        // TODO 参数验证、数据新增
        orgDto.setId(UUID.randomUUID().toString());
        return orgDto;
    }
}
2.2 编写请求服务类

NetServer

public class NetServer {
    private static final ExecutorService executorService = Executors.newFixedThreadPool(100);

    public static void start(int port) {
        try {
            ServerSocket serverSocket = new ServerSocket(port);
            while (true) {
                // 阻塞等待客户端连接
                Socket socket = serverSocket.accept();
                // 开启线程处理客户端连接
                executorService.submit(new RPCThreadProcessor(socket));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // 启动
        NetServer.start(8888);
    }
}
2.3 编写处理服务消费请求线程类

RPCThreadProcessor

public class RPCThreadProcessor implements Runnable {
    private Socket socket;

    public RPCThreadProcessor(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try (
                ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
                ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
        ) {
            Object object = inputStream.readObject();
            // 进行服务的调用与分发 Service Dispatch
            Object obj = ServiceDispatch.dispatch(object);
            outputStream.writeObject(obj);
            outputStream.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
2.4 编写服务的分发与调用类

ServiceDispatch

public class ServiceDispatch {

    public static Object dispatch(Object object) {
        RPCCommonReqDTO rpcCommonReqDTO = (RPCCommonReqDTO) object;
        String classPath = rpcCommonReqDTO.getClassPath();
        String methodName = rpcCommonReqDTO.getMethodName();
        Object[] args = rpcCommonReqDTO.getArgs();
        Class[] paramsClass = null;
        // 获取参数 Class 数组
        if (args != null && args.length > 0) {
            paramsClass = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                paramsClass[i] = args[i].getClass();
            }
        }
        Object obj = null;
        try {
            Class clazz = Class.forName(classPath);
            // 获取调用方法对象
            Method method = clazz.getDeclaredMethod(methodName, paramsClass);
        	// 通过反射的方式调用方法
            obj = method.invoke(clazz.newInstance(), args);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return obj;
    }
}

启动 rpc-provider 监听服务消费请求

3. Consumer

新建一个maven项目,项目结构如下在这里插入图片描述
引入 rpc-api 依赖

3.1 编写获取服务工厂类

ProxyFactory

public class ProxyFactory {

    public static <T> T getServiceInstance(Class<T> interfaceClass) {
        return (T) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {
        	/**
             * ProxyInstance
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                RPCCommonReqDTO rpcCommonReqDTO = new RPCCommonReqDTO();
                ImplAnnotion implAnnotion = interfaceClass.getAnnotation(ImplAnnotion.class);
                if (implAnnotion != null) {
                    rpcCommonReqDTO.setClassPath(implAnnotion.value());
                    rpcCommonReqDTO.setMethodName(method.getName());
                    rpcCommonReqDTO.setArgs(args);
                    // 通过 socket 调用服务
                    return NetClient.callServer("localhost", 8888, rpcCommonReqDTO);
                }
                return null;
            }
        });
    }
}
3.2 编写调用服务类

NetClient

public class NetClient {

    public static Object callServer(String host, int port, RPCCommonReqDTO rpcCommonReqDTO){
        Object obj = null;
        ObjectInputStream inputStream = null;
        ObjectOutputStream outputStream = null;
        try {
            Socket socket = new Socket(host, port);
            outputStream = new ObjectOutputStream(socket.getOutputStream());
            inputStream = new ObjectInputStream(socket.getInputStream());
            outputStream.writeObject(rpcCommonReqDTO);
            outputStream.flush();
            obj = inputStream.readObject();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null){
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null){
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return obj;
    }
}
3.3 调用测试
public class Call {

    public static void main(String[] args) {
        UserService userService = ProxyFactory.getServiceInstance(UserService.class);
        UserDTO user = new UserDTO();
        user.setName("test1");
        user.setAge(88);
        user.setSex("男");
        System.out.println("入参:" + user);
        System.out.println("出差:" + userService.addUser(user));
        System.out.println("=========================================================");
        OrgService orgService = ProxyFactory.getServiceInstance(OrgService.class);
        OrgDto org = new OrgDto();
        org.setName("财务部");
        org.setCode("CWB");
        org.setParentId("0");
        System.out.println("入参:" + org);
        System.out.println("出差:" + orgService.addOrg(org));
    }
}

执行结果:

入参:UserDTO(id=null, name=test1, age=88, sex=男)
出差:UserDTO(id=871f08a6-f537-4298-8b71-44a849a63842, name=test1, age=88, sex=男)
=========================================================
入参:OrgDto(id=null, parentId=0, name=财务部, code=CWB)
出差:OrgDto(id=e4bb7e3d-23ee-478c-867b-07e1f4465b64, parentId=0, name=财务部, code=CWB)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值