RPC-BDY(2)-注册多个服务
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)-注册多个服务相关推荐
- Dubbo学习笔记001---分布式服务调用_Dubbo简介_依赖zookeeper做为注册中心进行服务注册与发现
JAVA技术交流QQ群:170933152 Dubbo是阿里巴巴SOA服务化治理方案的核心框架,每天为2,000+个服务提供3,000,000,000+次访问量支持,并被广泛应用于阿里巴巴集团的各成员 ...
- [享学Eureka] 一、源生Eureka介绍 --- 基于注册中心的服务发现
凡事皆有代价,一切皆是取舍. 本专栏所有文章均计划逐步重写搬迁至本人公号:Java方向盘,且免费开放!故不再建议下单购买,可关注我公号前往免费学习.交流 –> 返回Netflix OSS套件专栏 ...
- Nacos服务注册与发现——服务发现
1.概览 1.1.什么是服务发现 在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标.这样在我们的代码中免不了要进行服务间的远程调用,服务的消费方要调用服务的生产方,为 ...
- Nacos服务注册中心(微服务)
为什么要用服务注册中心? 在微服务中,首先需要面对的问题就是如何查找服务(软件即服务), 其次就是如何在不同的服务之间进行通信? 如何更好更方便的管理应用中的每一个服务,如何建立各个服务之间联系的纽带 ...
- 通过jsl工具将java程序注册为windows服务
通过jsl工具将java程序注册为windows服务 首先下载jsl工具包,主要有jsl.exe可执行文件和jsl.ini配置信息文件 jsl 下载地址 在应用目录下新建以下几个路径 lib目录内容如 ...
- exe注册为service服务
本来这篇blog是"系统垃圾清理批处理"方面的,后面的批处理是我在工作中经常用的,经过了实践检验,不会引起系统问题,平时帮公司同事.朋友等清理系统垃圾就用下面的后面批处理. 这篇b ...
- oracle rac添加监听,【学习笔记】Oracle 10G RAC增加节点时手动注册监听服务的案例步骤...
[学习笔记]Oracle 10G RAC增加节点时手动注册监听服务的案例步骤 时间:2016-10-22 22:53 来源:Oracle研究中心 作者:HTZ 点击: 次 天萃荷净 Ora ...
- bat文件注册为Windows服务与依赖关系设置
文章目录 1. 批处理文件注册为服务 1.1 应用场景 1.2 操作步骤 1.2.1 编写批处理文件; 1.2.2 借助instsrv+srvany将批处理文件注册为服务: 1.2.3 设置服务之间的 ...
- 使用wrapper将java程序注册程windows服务后不生效
使用wrapper将java程序注册程windows服务后不生效 使用add.bat或test***.bat测试通过了, 然后使用install***.bat注册后cmd显示注册成功. 但是程序到了运 ...
- 没有Dubbo Admin,怎么查看zookeeper中注册的dubbo服务?
之前查看zookeeper中注册的dubbo服务,用的都是dubbo admin这种现成的工具. 旧版本dubbo admin长这样 (本图片来自网络) 新版本长这样 服务不太正常的时候,用dubbo ...
最新文章
- PostgreSQL 业务数据质量 实时监控 实践
- 2000行代码实现软渲染引擎
- C++知识点29——使用C++标准库(迭代器适配器)
- 132.非对称加密?数据安全的特征?
- 深入解析PHP中逗号与点号的区别
- 7-36 社交网络图中结点的“重要性”计算 (30 分)(思路加详解)兄弟们PTA乙级题目冲起来
- python缓冲区_如何在Python中使用Google的协议缓冲区
- 【slowfast 减少ava数据集】将ava数据集缩小到2个,对数据集做训练,然后进行检测,为训练自己的数据集做准备
- BMC之ipmitool 命令收集
- AutoCAD二次开发基础(二):曲线操作
- 文件服务器版压缩工具,FileOptimizer文件压缩工具
- 适合中小型企业的OA系统网上试用整理
- vue动态更改背景图
- Linux权限详解(chmod、600、644、700、711、755、777、4755、6755、7755)
- 高等数学、线性代数、概率论、几何这些知识可以用来干什么?
- 华为nova7 pro怎么升级鸿蒙,华为nova7升级到EMUI11,8大功能提升,带来更新体验
- 支持中标麒麟系统的运维监控软件——WGCLOUD
- 使用AWS中国区服务快速搭建LAMP
- python自动化键盘_使用Python进行鼠标和键盘自动化?
- 坚果手机刷linux,3/3T刷入Pt锤子SmartisanOS6的正确方法,解决3T区错误教程的问题...