手写rpc和redis
rpc框架搭建
consumer 消费者应用
provider 提供的服务
Provider-common 公共类模块
rpc 架构
service-Registration 服务发现
nacos nacos配置中心
load-balancing 负载均衡
redis-trench 手写redis实现和链接
package com.trench.protocol;import com.trench.enumUtil.RedisRepEnum;
import redis.clients.jedis.util.SafeEncoder;import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;public class Protocol {public static final String DOLLAR="$";public static final String STAR="*";public static final String BLANK="\r\n";public static void sendCommand(OutputStream outputStream, RedisRepEnum redisRepEnum,byte [] ... args){StringBuffer str=new StringBuffer();str.append(STAR).append(args.length-1).append(BLANK);str.append(DOLLAR).append(redisRepEnum.name().length()).append(BLANK);str.append(redisRepEnum).append(BLANK);Arrays.stream(args).forEach(arg->{str.append(DOLLAR).append(arg.length).append(BLANK);str.append(new String(arg)).append(BLANK);});try {outputStream.write(str.toString().getBytes(StandardCharsets.UTF_8));} catch (IOException e) {e.printStackTrace();}}public static final byte[] toByteArray(long value) {return SafeEncoder.encode(String.valueOf(value));}
}
package com.trench.api;import com.trench.connection.Connetion;
import com.trench.enumUtil.RedisRepEnum;
import com.trench.protocol.Protocol;
import com.trench.util.SerializeUtils;
import redis.clients.jedis.BuilderFactory;import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;public class Client {Connetion connetion;public Client(String host,Integer port){connetion=new Connetion(port,host);}public void set(final String key, final String values){connetion.sendCommand( RedisRepEnum.SET,key.getBytes(StandardCharsets.UTF_8), SerializeUtils.serialize(values));}public Object get(final String key){connetion.sendCommand(RedisRepEnum.GET,key.getBytes(StandardCharsets.UTF_8));return connetion.getData();}public void delete(final String key){connetion.sendCommand(RedisRepEnum.GETDEL,key.getBytes(StandardCharsets.UTF_8));}//封装redis的过期时间public void expire(String key, long seconds){connetion.sendCommand(RedisRepEnum.EXISTS, key.getBytes(StandardCharsets.UTF_8), Protocol.toByteArray(seconds));}//是否存在keypublic boolean exists(final String key) {connetion.sendCommand(RedisRepEnum.EXISTS, key.getBytes(StandardCharsets.UTF_8));return (Long)connetion.getData()==1L;}//查找key中set包含public Set<String> keys(final String key){connetion.sendCommand(RedisRepEnum.KEYS,key.getBytes(StandardCharsets.UTF_8));return (Set) BuilderFactory.STRING_SET.build((List)connetion.getData());}
}
rpc框架核心代码
package com.trench.protocol;import com.trench.SerializeUtils;
import com.trench.frawork.Invocation;
import com.trench.nacos.dome.NacosHttp;
import org.apache.commons.io.IOUtils;import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;public class HttpClient {public String send(String hostName, Integer port, Invocation invocation) throws IOException {//读取nacos中的配置用户的请求方式。如http POST get等NacosHttp nacosHttp=new NacosHttp();try {URL url=new URL(nacosHttp.getHttp(),hostName,port,nacosHttp.getFile());HttpURLConnection httpURLConnection= (HttpURLConnection)url.openConnection();httpURLConnection.setRequestMethod(nacosHttp.getRequestMethod());httpURLConnection.setDoOutput(true);//配置OutputStream outputStream=httpURLConnection.getOutputStream();ObjectOutputStream oss = new ObjectOutputStream(outputStream);oss.writeObject(SerializeUtils.serialize(invocation));oss.flush();oss.close();InputStream inputStream = httpURLConnection.getInputStream();return (String) SerializeUtils.deSerialize(IOUtils.toString(inputStream).getBytes(StandardCharsets.UTF_8));} catch (MalformedURLException e) {throw e;} catch (IOException e) {throw e;}}
}
启动tomcat
package com.trench.protocol;import org.apache.catalina.*;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.core.StandardEngine;
import org.apache.catalina.core.StandardHost;
import org.apache.catalina.startup.Tomcat;public class HttpServer {public void start(String hostname,Integer port){//读取用户配置Tomcat tomcat=new Tomcat();Server server = tomcat.getServer();Service service = server.findService("Tomcat");Connector connector=new Connector();connector.setPort(port);Engine engine=new StandardEngine();engine.setDefaultHost(hostname);Host host=new StandardHost();host.setName(hostname);String contextPash="";Context context=new StandardContext();context.setPath(contextPash);context.addLifecycleListener(new Tomcat.FixContextListener());host.addChild(context);engine.addChild(host);service.setContainer(engine);service.addConnector(connector);tomcat.addServlet(contextPash,"dispatcher",new DispatcherServlet());context.addServletMappingDecoded("/*","dispatcher");try {tomcat.start();tomcat.getServer().await();}catch (LifecycleException e){e.printStackTrace();}}
}
package com.trench.protocol;import com.trench.frawork.Invocation;
import com.trench.register.LocalRegister;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;public class HttpServerHandler extends HttpServer {public void handler(HttpServletRequest request, HttpServletResponse response){//可自行添加为心跳监听等操作//处理请求try {Invocation invocation = (Invocation)new ObjectInputStream(request.getInputStream()).readObject();String interfaceName =invocation.getInterfaceName();//接口名称Class aClass = LocalRegister.get(interfaceName,invocation.getVersion());Method method = aClass.getMethod(invocation.getMethodName(), invocation.getParameterTypes());String invoke = (String) method.invoke(aClass.newInstance(), invocation.getParameter());IOUtils.write(invoke.getBytes(StandardCharsets.UTF_8),response.getOutputStream());} catch (IOException e) {e.printStackTrace();}catch (ClassNotFoundException e){e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();}}
}
相关的gitub仓库地址:(https://github.com/zhaoyiwen-wuxian/RpcTrench.git) master分支,进行切换分支到master
相关文章:
手写rpc和redis
rpc框架搭建 consumer 消费者应用 provider 提供的服务 Provider-common 公共类模块 rpc 架构 service-Registration 服务发现 nacos nacos配置中心 load-balancing 负载均衡 redis-trench 手写redis实现和链接 package com.trench.protocol;import com.trench.enumUtil.Redis…...

Unity动画桢事件
1,使用原因 在新项目内部审核的时候,说什么动画节奏不匹配,所以决定用动画桢事件来处理技能释放。当释放技能的时候,先播放技能动画,然后再动画桢所在的时间戳执行技能的逻辑。 2,具体实现 1,…...

搭建Redis集群
一 应用场景 为什么需要redis集群? 当主备复制场景,无法满足主机的单点故障时,需要引入集群配置。 一般数据库要处理的读请求远大于写请求 ,针对这种情况,我们优化数据库可以采用读写分离的策略。我们可以部 署一台…...
C语言sizeof 不是函数吗?
一、问题 sizeof 怎么⽤,它不是函数吗? 二、解答 sizeof 在 C 和 C 中不是一个函数,而是一个运算符。它在编译时计算其操作数所占用的内存大小,并返回一个大小(字节数),这个结果是类型或表达式…...
Mybatis的XML配置
MyBatis 是一个持久层框架,通过 XML 配置文件来定义 SQL 映射和结果的映射规则。以下是关于 MyBatis XML 配置文件的详细说明: 基本结构: XML 配置文件通常包含 <mapper>、<resultMap>、<typeAliases> 等元素。 2. mappe…...
Oracle报错:ORA-08002: sequence CURRVAL is not yet defined in this session
问题 直接查询序列的当前值,然后报了这个错误。 SELECT HR.EMPLOYEES_SEQ.CURRVAL; ORA-08002: sequence CURRVAL is not yet defined in this session解决 ORA-08002错误是Oracle数据库中的一个常见错误,它表示在当前会话中未定义序列的CURRVAL值。这…...

python10-Python的字符串之拼接字符串
如果直接将两个字符串紧挨着写在一起,Python就会自动拼接它们,例如如下代码。 s1 "软件测试划水老师傅,"软件测试老痞print(s1) 上面代码将会输出: 软件测试划水老师傅,软件测试老痞 上面这种写法只是书写字符串的一…...

华为三层交换机之基本操作
Telnet简介 Telnet是一个应用层协议,可以在Internet上或局域网上使用。它提供了基于文本的远程终端接口,允许用户在本地计算机上登录到远程计算机,然后像在本地计算机上一样使用远程计算机的资源。Telnet客户端和服务器之间的通信是通过Telnet协议进行的…...

IntelliJ IDEA 快捷键大全
IntelliJ IDEA 快捷键大全 一、文本编辑二、构建、编译项目 一、文本编辑 CtrlN 查找类 CtrlN 查找文件 CtrlF 查找文本 可以根据需求去选择红框内的选项 CtrlX 剪切 剪切选中文本,如果未选中则剪切当前行CtrlC 复制 复制选中文本,如果未选中则复制当前…...

scrapy的概念作用和工作流程
1. scrapy的概念 Scrapy是一个Python编写的开源网络爬虫框架。它是一个被设计用于爬取网络数据、提取结构性数据的框架。 Scrapy 使用了Twisted[twɪstɪd]异步网络框架,可以加快我们的下载速度。 Scrapy文档地址:http://scrapy-chs.readthedocs.io/zh_…...
首页热卖推荐商品显示axios异步请求数据动态渲染实现
flex-wrap属性: 默认情况下,项目都排在一条线(又称“轴线”)上。flex- wrap属性定义,如果一条轴线 排不下,如何换行? flex-wrap:wrap 该样式用于设置 换行。 .product_name{white-space: nowrap…...

【C++11并发】mutex 笔记
简介 在多线程中往往需要访问临界资源,C11为我们提供了mutex等相关类来保护临界资源,保证某一时刻只有一个线程可以访问临界资源。主要包括各种mutex,他们的命名大都是xx_mutex。以及RAII风格的wrapper类,RAII就是一般在构造的时…...

洛谷 P5635 【CSGRound1】天下第一
原址链接 P5635 【CSGRound1】天下第一 先看标签 搜索?模拟?用不着这么复杂 创建函数a(int x,int y,int p) a(int x,int y,int p){if(x<0){return 1;}x (xy)%p;if(y<0){return 2;}y (xy)%p;return a(x,y,p); }写入主函数 #include<iostrea…...
如何通过Navicat远程访问宝塔面板安装的MySQL数据库
Navicat报错信息: 错误代码 1045 Access denied for user ‘root’’219.144.205.81’ (using password:YES) —— 没有权限的访问的报错 1.宝塔面板 > 放行端口:3306 2.阿里云安全组 > 放行端口:3306 3.配置mysql3306端口 4.使用Xshell 链接服务器 m…...
【硅谷甄选】导航守卫(进度条,网页标题,路由鉴权)
import setting from /setting import router from /router // 任意路由切换实现进度条业务: nprogress插件 import nprogress from nprogress // js插件在ts中的报错 // 引入进度条样式 import nprogress/nprogress.css // 表示在加载进度条时不显示加载小图标 np…...

OpenHarmony—TypeScript到ArkTS约束说明
对象的属性名必须是合法的标识符 规则:arkts-identifiers-as-prop-names 级别:错误 在ArkTS中,对象的属性名不能为数字或字符串。通过属性名访问类的属性,通过数值索引访问数组元素。 TypeScript var x { name: x, 2: 3 };c…...

蓝桥杯——每日一练(简单题)
题目 有n个整数,使前面各数顺序向后移m个位置,最后m个数变成前面m个数。写一函数:实现以上功能,在主函数中输入n个数和输出调整后的n个数。 解析 一、list()函数配合map()函数获得…...

css设置不可点击
文章目录 一、前言二、MDN三、使用四、注意五、总结六、最后 一、前言 在网页开发中,经常会遇到一种情况,就是需要将某个元素的点击事件屏蔽,使其在用户点击时没有任何反应。这时候,我们可以通过CSS的pointer-events属性设置为no…...

fastapi学习
fastapi框架 fastapi,一个用于构建 API 的现代、快速(高性能)的web框架。 fastapi是建立在Starlette和Pydantic基础上的,Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工…...

【代码随想录-数组】长度最小的子数组
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学习,不断总结,共同进步,活到老学到老导航 檀越剑指大厂系列:全面总结 jav…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

STM32F4基本定时器使用和原理详解
STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...