RPC-BDY(2)

早起的鸟儿不该是牢笼的困兽

-2022.7.14


文章目录

  • RPC-BDY(2)
  • 前言
  • 一、服务注册表
  • 二、请求处理
  • 三、服务类和测试类
  • 四、知识
  • 总结

前言

在上一节最简单实现里,只能注册一个服务,现在把服务和注册两个分开实现,保证能提供多个服务


一、服务注册表

1.服务注册表接口
通过注册服务和获取服务的功能


/*** 服务注册接口*/
public interface ServiceRegistry {//注册方法public <T> void registry(T service);//获取方法public Object getService(String serviceName);
}

2.服务注册表实现类


/*** 服务注册实现类*/
public class DefaultServiceRegistry implements ServiceRegistry{private static final Logger logger = LoggerFactory.getLogger(DefaultServiceRegistry.class);//ConcurrentHashMap线程安全final Map<String, Object> serviceMap = new ConcurrentHashMap<>();final Set<String> serviceSet = ConcurrentHashMap.newKeySet();@Overridepublic <T> void registry(T service) {//将方法名添加到set中String serviceName = service.getClass().getCanonicalName();if(serviceSet.contains(serviceName)) return;serviceSet.add(serviceName);//获取类实现的接口Class<?>[] interfaces = service.getClass().getInterfaces();if (interfaces.length==0) {throw new RpcException(RpcError.SERVICE_NOT_IMPLEMENT_ANY_INTERFACE);}for(Class<?> i : interfaces) {//接口名称:服务serviceMap.put(i.getCanonicalName(), service);}logger.info("向接口: {} 注册服务: {}", interfaces, serviceName);}@Override//传过来的serviceName代表的就是接口名称public Object getService(String serviceName) {//在map中找到名称对应的服务Object service = serviceMap.get(serviceName);if(service == null) {throw new RpcException(RpcError.SERVICE_NOT_FOUND);}return service;}
}

二、请求处理

1.请求处理类

/*** 请求处理类*/
public class RequestHandler {private static final Logger logger = LoggerFactory.getLogger(RequestHandler.class);//request请求信息,service服务实例化后的对象public Object handle(RpcRequest rpcRequest, Object service) {//反射调用try {//传入方法名和参数类型找到对应的方法Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());logger.info("服务:{} 成功调用方法:{}", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());//service:实例化后的对象return method.invoke(service, rpcRequest.getParameters());} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {logger.error("调用或发送时有错误发生:", e);}return RpcResponse.fail(ResponseCode.METHOD_NOT_FOUND);}
}

2.请求处理线程

/*** 请求处理线程*/
public class RequestHandlerThread implements Runnable{private static final Logger logger = LoggerFactory.getLogger(RequestHandlerThread.class);private Socket socket;private RequestHandler requestHandler;private ServiceRegistry serviceRegistry;public RequestHandlerThread(Socket socket, RequestHandler requestHandler, ServiceRegistry serviceRegistry) {this.socket = socket;this.requestHandler = requestHandler;this.serviceRegistry = serviceRegistry;}@Overridepublic void run() {try {ObjectInputStream objectInputStream = new ObjectInputStream(socket.getInputStream());ObjectOutputStream objectOutputStream = new ObjectOutputStream(socket.getOutputStream());RpcRequest rpcRequest = (RpcRequest) objectInputStream.readObject();Object service = serviceRegistry.getService(rpcRequest.getInterfaceName());Object handle = requestHandler.handle(rpcRequest, service);objectOutputStream.writeObject(RpcResponse.success(handle));objectOutputStream.flush();} catch (IOException | ClassNotFoundException e) {logger.error("调用或发送时有错误发生:", e);}}
}

三、服务类和测试类

1.服务类


public class RpcServer  {private static final Logger logger = LoggerFactory.getLogger(RpcServer.class);private static final int CORE_POOL_SIZE = 5;private static final int MAXIMUM_POOL_SIZE = 50;private static final int KEEP_ALIVE_TIME = 60;private static final int BLOCKING_QUEUE_CAPACITY = 100;private final ExecutorService threadPool;private RequestHandler requestHandler = new RequestHandler();private final ServiceRegistry serviceRegistry;//创建线程池//将注册表放到服务器上public RpcServer(ServiceRegistry serviceRegistry) {this.serviceRegistry = serviceRegistry;BlockingQueue<Runnable> workingQueue = new ArrayBlockingQueue<>(BLOCKING_QUEUE_CAPACITY);ThreadFactory threadFactory = Executors.defaultThreadFactory();threadPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workingQueue, threadFactory);}//开启服务public void start(int port){try {ServerSocket serverSocket = new ServerSocket(port);logger.info("服务器启动……");Socket socket; while((socket = serverSocket.accept()) != null) {logger.info("消费者连接: {}:{}", socket.getInetAddress(), socket.getPort());threadPool.execute(new RequestHandlerThread(socket, requestHandler, serviceRegistry));}threadPool.shutdown();} catch (IOException e) {logger.error("服务器启动时有错误发生:", e);}}}

2.测试类


public class TestSerer2 {public static void main(String[] args) {HelloService helloService = new HelloServiceImpl();ServiceRegistry registry = new DefaultServiceRegistry();registry.registry(helloService);RpcServer rpcServer = new RpcServer(registry);rpcServer.start(9001);}
}

四、知识

1.ConcurrentHashMap

ConcurrentHashmap保证线程安全的方式:乐观锁+Sysnchronized

2.socket和serverSocket

serversocket:要实现一个服务器应用,需要不同的做法。服务器需随时待命,因为不知道客户端什么时候会发来请求,此时,我们需要使用ServerSocket
ServerSocket与Socket不同,ServerSocket是等待客户端的请求,一旦获得一个连接请求,就创建一个Socket示例来与客户端进行通信

3.registry中的service参数是什么意思?

在registry.registry(helloService);中,HelloService就是service
所以service代表的是接口实现类的实例对象


总结

大概知道了动态代理和反射实现方法了

RPC-BDY(2)-注册多个服务相关推荐

  1. Dubbo学习笔记001---分布式服务调用_Dubbo简介_依赖zookeeper做为注册中心进行服务注册与发现

    JAVA技术交流QQ群:170933152 Dubbo是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员 ...

  2. [享学Eureka] 一、源生Eureka介绍 --- 基于注册中心的服务发现

    凡事皆有代价,一切皆是取舍. 本专栏所有文章均计划逐步重写搬迁至本人公号:Java方向盘,且免费开放!故不再建议下单购买,可关注我公号前往免费学习.交流 –> 返回Netflix OSS套件专栏 ...

  3. Nacos服务注册与发现——服务发现

    1.概览 1.1.什么是服务发现 在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标.这样在我们的代码中免不了要进行服务间的远程调用,服务的消费方要调用服务的生产方,为 ...

  4. Nacos服务注册中心(微服务)

    为什么要用服务注册中心? 在微服务中,首先需要面对的问题就是如何查找服务(软件即服务), 其次就是如何在不同的服务之间进行通信? 如何更好更方便的管理应用中的每一个服务,如何建立各个服务之间联系的纽带 ...

  5. 通过jsl工具将java程序注册为windows服务

    通过jsl工具将java程序注册为windows服务 首先下载jsl工具包,主要有jsl.exe可执行文件和jsl.ini配置信息文件 jsl 下载地址 在应用目录下新建以下几个路径 lib目录内容如 ...

  6. exe注册为service服务

    本来这篇blog是"系统垃圾清理批处理"方面的,后面的批处理是我在工作中经常用的,经过了实践检验,不会引起系统问题,平时帮公司同事.朋友等清理系统垃圾就用下面的后面批处理. 这篇b ...

  7. oracle rac添加监听,【学习笔记】Oracle 10G RAC增加节点时手动注册监听服务的案例步骤...

    [学习笔记]Oracle 10G RAC增加节点时手动注册监听服务的案例步骤 时间:2016-10-22 22:53   来源:Oracle研究中心   作者:HTZ   点击: 次 天萃荷净 Ora ...

  8. bat文件注册为Windows服务与依赖关系设置

    文章目录 1. 批处理文件注册为服务 1.1 应用场景 1.2 操作步骤 1.2.1 编写批处理文件; 1.2.2 借助instsrv+srvany将批处理文件注册为服务: 1.2.3 设置服务之间的 ...

  9. 使用wrapper将java程序注册程windows服务后不生效

    使用wrapper将java程序注册程windows服务后不生效 使用add.bat或test***.bat测试通过了, 然后使用install***.bat注册后cmd显示注册成功. 但是程序到了运 ...

  10. 没有Dubbo Admin,怎么查看zookeeper中注册的dubbo服务?

    之前查看zookeeper中注册的dubbo服务,用的都是dubbo admin这种现成的工具. 旧版本dubbo admin长这样 (本图片来自网络) 新版本长这样 服务不太正常的时候,用dubbo ...

最新文章

  1. PostgreSQL 业务数据质量 实时监控 实践
  2. 2000行代码实现软渲染引擎
  3. C++知识点29——使用C++标准库(迭代器适配器)
  4. 132.非对称加密?数据安全的特征?
  5. 深入解析PHP中逗号与点号的区别
  6. 7-36 社交网络图中结点的“重要性”计算 (30 分)(思路加详解)兄弟们PTA乙级题目冲起来
  7. python缓冲区_如何在Python中使用Google的协议缓冲区
  8. 【slowfast 减少ava数据集】将ava数据集缩小到2个,对数据集做训练,然后进行检测,为训练自己的数据集做准备
  9. BMC之ipmitool 命令收集
  10. AutoCAD二次开发基础(二):曲线操作
  11. 文件服务器版压缩工具,FileOptimizer文件压缩工具
  12. 适合中小型企业的OA系统网上试用整理
  13. vue动态更改背景图
  14. Linux权限详解(chmod、600、644、700、711、755、777、4755、6755、7755)
  15. 高等数学、线性代数、概率论、几何这些知识可以用来干什么?
  16. 华为nova7 pro怎么升级鸿蒙,华为nova7升级到EMUI11,8大功能提升,带来更新体验
  17. 支持中标麒麟系统的运维监控软件——WGCLOUD
  18. 使用AWS中国区服务快速搭建LAMP
  19. python自动化键盘_使用Python进行鼠标和键盘自动化?
  20. 坚果手机刷linux,3/3T刷入Pt锤子SmartisanOS6的正确方法,解决3T区错误教程的问题...

热门文章

  1. 电脑最好用的服务器系统是,求电脑高手推荐一台服务器,最好是惠普的
  2. 一种可以从零速度启动的航空冲压发动机
  3. ORACLE 记录连接用户的IP地址以及登录失败用户的IP地址
  4. ZPL打印二维码、汉字
  5. rebar3使用介绍(七)测试
  6. 网上商城购物系统的优势和建站方法
  7. 液压机的全球与中国市场2022-2028年:技术、参与者、趋势、市场规模及占有率研究报告
  8. 自媒体运营教程:关于百家号内容质量的一些解析,新手必看!
  9. 2020T电梯修理模拟考试题及T电梯修理考试软件
  10. 魔方机器人(基于OpenCV、Arduino)