一个简单的rpc框架的实现

【远程调用框架】如何实现一个简单的RPC框架(二)实现与使用 【如何实现一个简单的RPC框架】系列文章:【远程调用框架】如何实现一个简单的RPC框架(一)想法与设计 【远程调用框架】如何实现一个简单的RPC框架(二)实现与使用 【远程调用框架】如何实现一个简单的RPC框架(三)优化一:利用动态代理改变用户服务调用方式 【远程调用框架】如何实现一个简单的RPC框架(四)优化二:改变底层通信框架 【远程调用框架】如何实现一个简单的RPC框架(五)优化三:软 阅读详情

package com.cgs.nettytest;

import java.net.InetSocketAddress;

import com.cgs.nio.RpcRequest;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class EchoClient {
	
	private String host;
	
	private int port;
	
	private static EventLoopGroup group = new NioEventLoopGroup();
	
	private static Bootstrap b = new Bootstrap();
	
	private  RpcRequest rpcRequest;
	
	public EchoClient(String host,int port){
		this.host = host;
		this.port = port;
	}
	
	public EchoClient(){
		init();
	}
	
	public void init(){
		this.host = "127.0.0.1";
		this.port = 20000;
	}
	
	public void setRpcRequest(RpcRequest rpcRequest){
		this.rpcRequest = rpcRequest;
	}
	
	public void start() throws Exception{
		b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(this.host,this.port)).handler(new ChannelInitializer(){

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					System.out.println("connected..");
					ch.pipeline().addLast(new EchoClientHandler(rpcRequest));
				}
		});
		ChannelFuture cf = b.connect().sync();
		System.out.println("connected compelete");
	}
	
	public void close() throws Exception{
		
		System.out.println("connected compelete");
		System.out.println("closed..");
		group.shutdownGracefully().sync(); // 释放线程池资源
	}
	
	public static void main(String[] args) {
		try {
			new EchoClient("127.0.0.1", 20000).start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 连接127.0.0.1/65535,并启动
	}
}
(){

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					System.out.println("connected..");
					ch.pipeline().addLast(new EchoClientHandler(rpcRequest));
				}
		});
		ChannelFuture cf = b.connect().sync();
		System.out.println("connected compelete");
	}
	
	public void close() throws Exception{
		
		System.out.println("connected compelete");
		System.out.println("closed..");
		group.shutdownGracefully().sync(); // 释放线程池资源
	}
	
	public static void main(String[] args) {
		try {
			new EchoClient("127.0.0.1", 20000).start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 连接127.0.0.1/65535,并启动
	}
}

        远程过程调用协议,基于C/S模型,其主要核心就是调用远程方法就和调用本地方法形式几乎一样,rpc框架隐藏了底层的数据传输的细节,能够让人更加方便的写出分布式的程序。下图展现了一个典型的rpc框架的运行过程:

      

  以上是一个基于java平台的rpc框架的调用过程。下面笔者用开源的netty网络库实现一个rpc框架,技术背景:netty,cglib。

实现的关键点: 1.动态代理。2.消息的封装。

首先给客户端调用的代码写一个动态代理:package com.cgs.nio;

import java.lang.reflect.Method;

import com.cgs.nettytest.EchoClient;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class RpcCglibClientProxy implements MethodInterceptor{

private static RpcCglibClientProxy proxy = new RpcCglibClientProxy();

private static EchoClient echoClient = new EchoClient();

private Object target;

public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// TODO Auto-generated method stub
RpcRequest rpcRequest = new RpcRequest();
String className = object.getClass().getName();
rpcRequest.setRequestId(String.valueOf(System.currentTimeMillis()));
rpcRequest.setMethodName(method.getName());
rpcRequest.setParameters(args);
rpcRequest.setParameterTypes(method.getParameterTypes());
rpcRequest.setClassName(object.getClass().getName());
echoClient.setRpcRequest(rpcRequest);
echoClient.start();
echoClient.close();;
return null;
}

public Object createProxy(Class classzz){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(classzz);
enhancer.setCallback(this);
return enhancer.create();
}
public static RpcCglibClientProxy getInstance(){
return proxy;
}

public static void main(String[] args) {
TestInterface object = (TestInterface) RpcCglibClientProxy.getInstance().createProxy(TestInterface.class);
object.testMethod("test");
}
}

动态代理的功能是将为客户端调用的接口额外生成一个代理,用来替换掉其原本的接口方法,在代理的方法中,新建一个rpc客户端,并且获取方法的名称和参数,以及参数的类型,将其封装为一个请求消息的实体。通过rpc的客户端将其序列化之后,通过客户端向服务器端发送消息。消息实体的代码如下

该实体主要是封装了以下的几个属性:1.消息id.2调用的接口的类名。3.调用的方法名.4.调用的参数值,调用的参数类型。消息实体主要是为了服务端的反射提供数据类型。

      

epackage com.cgs.nio;

import java.io.Serializable;

public class RpcRequest implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 5186013065336159778L;

	private String requestId;
	
	private String className;
	
	private String methodName;
	
	private Class[] parameterTypes;
	
	private Object[] parameters;

	public String getRequestId() {
		return requestId;
	}

	public void setRequestId(String requestId) {
		this.requestId = requestId;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public Class[] getParameterTypes() {
		return parameterTypes;
	}

	public void setParameterTypes(Class[] classes) {
		this.parameterTypes = classes;
	}

	public Object[] getParameters() {
		return parameters;
	}

	public void setParameters(Object[] parameters) {
		this.parameters = parameters;
	}
	
	
}
package com.cgs.nettytest;

import java.net.InetSocketAddress;

import com.cgs.nio.RpcRequest;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class EchoClient {
	
	private String host;
	
	private int port;
	
	private static EventLoopGroup group = new NioEventLoopGroup();
	
	private static Bootstrap b = new Bootstrap();
	
	private  RpcRequest rpcRequest;
	
	public EchoClient(String host,int port){
		this.host = host;
		this.port = port;
	}
	
	public EchoClient(){
		init();
	}
	
	public void init(){
		this.host = "127.0.0.1";
		this.port = 20000;
	}
	
	public void setRpcRequest(RpcRequest rpcRequest){
		this.rpcRequest = rpcRequest;
	}
	
	public void start() throws Exception{
		b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(this.host,this.port)).handler(new ChannelInitializer(){

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					System.out.println("connected..");
					ch.pipeline().addLast(new EchoClientHandler(rpcRequest));
				}
		});
		ChannelFuture cf = b.connect().sync();
		System.out.println("connected compelete");
	}
	
	public void close() throws Exception{
		
		System.out.println("connected compelete");
		System.out.println("closed..");
		group.shutdownGracefully().sync(); // 释放线程池资源
	}
	
	public static void main(String[] args) {
		try {
			new EchoClient("127.0.0.1", 20000).start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 连接127.0.0.1/65535,并启动
	}
}
[] parameterTypes;
	
	private Object[] parameters;

	public String getRequestId() {
		return requestId;
	}

	public void setRequestId(String requestId) {
		this.requestId = requestId;
	}

	public String getClassName() {
		return className;
	}

	public void setClassName(String className) {
		this.className = className;
	}

	public String getMethodName() {
		return methodName;
	}

	public void setMethodName(String methodName) {
		this.methodName = methodName;
	}

	public Class[] getParameterTypes() {
		return parameterTypes;
	}

	public void setParameterTypes(Class[] classes) {
		this.parameterTypes = classes;
	}

	public Object[] getParameters() {
		return parameters;
	}

	public void setParameters(Object[] parameters) {
		this.parameters = parameters;
	}
	
	
}
package com.cgs.nettytest;

import java.net.InetSocketAddress;

import com.cgs.nio.RpcRequest;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class EchoClient {
	
	private String host;
	
	private int port;
	
	private static EventLoopGroup group = new NioEventLoopGroup();
	
	private static Bootstrap b = new Bootstrap();
	
	private  RpcRequest rpcRequest;
	
	public EchoClient(String host,int port){
		this.host = host;
		this.port = port;
	}
	
	public EchoClient(){
		init();
	}
	
	public void init(){
		this.host = "127.0.0.1";
		this.port = 20000;
	}
	
	public void setRpcRequest(RpcRequest rpcRequest){
		this.rpcRequest = rpcRequest;
	}
	
	public void start() throws Exception{
		b.group(group).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(this.host,this.port)).handler(new ChannelInitializer(){

				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					System.out.println("connected..");
					ch.pipeline().addLast(new EchoClientHandler(rpcRequest));
				}
		});
		ChannelFuture cf = b.connect().sync();
		System.out.println("connected compelete");
	}
	
	public void close() throws Exception{
		
		System.out.println("connected compelete");
		System.out.println("closed..");
		group.shutdownGracefully().sync(); // 释放线程池资源
	}
	
	public static void main(String[] args) {
		try {
			new EchoClient("127.0.0.1", 20000).start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} // 连接127.0.0.1/65535,并启动
	}
}
服务器通过收到客户端传过来的数据将其反序列化,通过反射的机制创建对应的类和方法的实例并且执行,执行完成之后将其封装为一个Response消息实体。作为一个服务有多种形式可以提供,为了方便,本文采取了jar包的方式来提供对应的服务。为此特意写了一个读取jar包的辅助类:



package com.cgs.io;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import com.cgs.config.Config;

public class JarUtil {
	
	private static List classzz = new ArrayList();
	
	private static JarFile jarFile = null;
	
	private static String staticPath = "file:f:/test.jar";
	
	private static ConcurrentHashMap hashMap = new ConcurrentHashMap();
	
	
	static{
//		try {
//			loadFilePath(Config.getLoadJarPath());
//		} catch (Exception e){
//			throw new RuntimeException(e);
//		}
	}
	
	public static void loadFilePath(String filepath) throws IOException, ClassNotFoundException{
		jarFile = new JarFile(filepath);
		List jarEntryList = new ArrayList();
		Enumeration ee = jarFile.entries();
		while(ee.hasMoreElements()){
			JarEntry entry = (JarEntry)ee.nextElement();
			if(entry.getName().contains(".class") && !entry.getName().contains("classpath")){
				jarEntryList.add(entry);
			}
		}
		URL url = new URL(staticPath);
		URL[] urls = new URL[]{url};
		URLClassLoader loader = new URLClassLoader(urls);
		for(JarEntry entry : jarEntryList){
			String className = entry.getName().replace('/', '.');
			className = className.substring(0, className.length() - 6);
			Class c = loader.loadClass(className);
			if(!c.isInterface()){
				hashMap.put(className, c);
			}
			
		}
		loader.close();
	}
	
	public void loadClassFile(File[] jarFiles){
		if(jarFiles != null){
			try {
				Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
				boolean accessible = method.isAccessible();
				if(accessible){
					method.setAccessible(true);
				}
				URLClassLoader classLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
				
		} catch (Exception e) {
				
			}
		}
	}
		
	public static ConcurrentHashMap getHashMap() {
		return hashMap;
	}

	public static void main(String[] args) {
		String filePath = "F:/test.jar";
		try {
			JarUtil.loadFilePath(filePath);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
 classzz = new ArrayList();
	
	private static JarFile jarFile = null;
	
	private static String staticPath = "file:f:/test.jar";
	
	private static ConcurrentHashMap hashMap = new ConcurrentHashMap();
	
	
	static{
//		try {
//			loadFilePath(Config.getLoadJarPath());
//		} catch (Exception e){
//			throw new RuntimeException(e);
//		}
	}
	
	public static void loadFilePath(String filepath) throws IOException, ClassNotFoundException{
		jarFile = new JarFile(filepath);
		List jarEntryList = new ArrayList();
		Enumeration ee = jarFile.entries();
		while(ee.hasMoreElements()){
			JarEntry entry = (JarEntry)ee.nextElement();
			if(entry.getName().contains(".class") && !entry.getName().contains("classpath")){
				jarEntryList.add(entry);
			}
		}
		URL url = new URL(staticPath);
		URL[] urls = new URL[]{url};
		URLClassLoader loader = new URLClassLoader(urls);
		for(JarEntry entry : jarEntryList){
			String className = entry.getName().replace('/', '.');
			className = className.substring(0, className.length() - 6);
			Class c = loader.loadClass(className);
			if(!c.isInterface()){
				hashMap.put(className, c);
			}
			
		}
		loader.close();
	}
	
	public void loadClassFile(File[] jarFiles){
		if(jarFiles != null){
			try {
				Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
				boolean accessible = method.isAccessible();
				if(accessible){
					method.setAccessible(true);
				}
				URLClassLoader classLoader = (URLClassLoader)ClassLoader.getSystemClassLoader();
				
		} catch (Exception e) {
				
			}
		}
	}
		
	public static ConcurrentHashMap getHashMap() {
		return hashMap;
	}

	public static void main(String[] args) {
		String filePath = "F:/test.jar";
		try {
			JarUtil.loadFilePath(filePath);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
}
将对应的服务jar包读取进来,为此通过反射机制建立对应的对象实例并且执行后,后端通过触发的对应事件,将执行的结果封装为一个Response返回给客户端,Response代码如下:
      
package com.cgs.nio;

import java.io.Serializable;

public class RpcResponse implements Serializable{


	private static final long serialVersionUID = 1L;

	private String requestId;
	
	private Throwable error;
	
	private Object result;

	public String getRequestId() {
		return requestId;
	}

	public void setRequestId(String requestId) {
		this.requestId = requestId;
	}

	public Throwable getError() {
		return error;
	}

	public void setError(Throwable error) {
		this.error = error;
	}

	public Object getResult() {
		return result;
	}

	public void setResult(Object result) {
		this.result = result;
	}
	
	
}
服务端对应的代码如下(不过服务端暂时还没有写完,以后会补上):
package com.cgs.nettytest;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class EchoServer {

	private final int port;
	
	public EchoServer(int port){
		this.port = port;
	}
	
	public void start() throws Exception{
		EventLoopGroup group = new NioEventLoopGroup();
		try{
			ServerBootstrap sb = new ServerBootstrap();
			sb.group(group).channel(NioServerSocketChannel.class).localAddress(this.port).childHandler(new ChannelInitializer(){
				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					System.out.println("connect... Client: " + ch.remoteAddress());
					ch.pipeline().addLast(new EchoServerHandler());
				}
			});
			ChannelFuture cf = sb.bind().sync();
			cf.channel().closeFuture().sync();
		}finally{
			group.shutdownGracefully().sync();
		}
	}
	
	public static void main(String[] args) {
		try {
			new EchoServer(20000).start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
(){
				@Override
				protected void initChannel(SocketChannel ch) throws Exception {
					// TODO Auto-generated method stub
					System.out.println("connect... Client: " + ch.remoteAddress());
					ch.pipeline().addLast(new EchoServerHandler());
				}
			});
			ChannelFuture cf = sb.bind().sync();
			cf.channel().closeFuture().sync();
		}finally{
			group.shutdownGracefully().sync();
		}
	}
	
	public static void main(String[] args) {
		try {
			new EchoServer(20000).start();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
服务端读取普通的jar包来做服务,以上一个简单的rpc框架就基本实现完成。其实个人觉得这玩意原理到不是很难,主要的难点在于多线程的并发控制,以及负载均衡,服务的监控,日志的处理,这些才是rpc框架的精髓所在。。

从半导体物理到实战:手把手教你测量MOS管体二极管的Vf和Trr 本文深入探讨了MOSFET体二极管的关键参数测量方法,重点讲解了正向压降(Vf)和反向恢复时间(Trr)的测量原理与实战步骤。通过搭建测试平台,使用万用表和示波器等工具,手把手指导如何量化这些影响开关损耗和效率的核心参数,并对比分析了硅基与碳化硅(SiC)器件在体二极管性能上的显著差异。 阅读详情

相关推荐

KUKA机器人 - 从开机到自动运行

注1:本文仅代表本人对机器人使用的一些建议,在使用机器人前,还请详细阅读库卡机器人官方资料,道路千万条,安全第一条!!! 注2:技术有限,欢迎各位大大在阅读过程中发现各类问题,并且批评指正!!! 目录 一、准备工作 1. 机器人上电完成 2. 电脑安装Workvisual 二、学习手动移动机器人 三、项目配置 1. 设置机器人IP地址 2.电脑和机器人通过网线连接 3.查找并打开项目 4. 通讯配置 5. 项目上传 6. 检验IO配置 四、编程 1.新建程序 2. 程序...

yilunyao的博客 1万+

RPC - 如何动手实现一个简单RPC框架 - 学习/实践

主要用于学习RPC的原理,工作流程,拆解和组装一个简单的RPC框架。

"代码"的日常搬运 2519

AGI 之 【Dify】 之 Dify 在 Windows 端本地部署调用 Ollama 本地下载的大模型, API 形式 Python 调用 进行简单聊天接口测试

AGI,即通用人工智能(Artificial General Intelligence),是一种具备人类智能水平的人工智能系统。它不仅能够执行特定的任务,而且能够理解、学习和应用知识于广泛的问题解决中,具有较高的自主性和适应性。AGI的能力包括但不限于自我学习、自我改进、自我调整,并能在没有人为干预的情况下解决各种复杂问题。本节将介绍如何使用 Dify 平台调用 Ollama 部署的本地模型来创建一个聊天应用。通过 API 的方式发起聊天,可以让前端自由布置所需的聊天形式。

仙魁XAN 1万+

RPC框架(一)——简易RPC

RPC框架(一)——简易RPC

mao____mao的博客 834

ENVI学习总结(十二)——基于改进的 CASA 模型反演 NPP

基于改进的 CASA 模型反演 NPP 数据为地理空间数据云提供的 TM 影像,其具体信息如图 1 所示。该实验中所使用的 TM 数据已进行过 QUAC 快速大气校正,来消除大气和光照等因素对地物反射的影响。Landsat 主题成像仪(TM)是 Landsat4 和 Landsat5 携带的传感器,每 16 天扫描同一地区,即 16 天覆盖全球一次。 TM 影像包含 7 个波段,波段 1-5 ...

Arcgiser的博客 3万+

uniapp | vue2 | vue3 - 解决调用天地图功能服务时 http 网络请求报错 net::ERR ABORTED 503(Service Temporarily Unavailabl)

vue,uni-app,天地图,请求报错,503,请求失败,map.tianditu,天地图503,天地图请求503,接口503错误怎么办,vue天地图,uniAPP天地图,获取定位接口服务器报错503,获取当前定位,定位功能,IP属地定位,天地图服务器报错,如何解决报错,net::ERRABORTED503(ServiceTemporarilyUnavailabl),GET,POST,服务暂时不可用,react天地图,一直等待吗,报错怎么办,定位报错,轨迹,经纬度,天地图服务器503,在vue2

🏆 前端领域优质创作者 4438

自己动手实现rpc框架(一) 实现点对点的rpc通信

RPC是远过程调用(Remote Procedure Call)的缩写形式,其区别于一个程序内部基本的过程调用(或者叫函数/方法调用)。随着应用程序变得越来越复杂,在单个机器上中仅通过一个进程来运行整个应用程序的方式已经难以满足现实中日益增长的需求。开发者对应用程序进行模块化的拆分,以分布式部署的方式来降低程序整体的复杂度和提升性能方面的可拓展性(分而治之的思想)。拆分后部署在不同机器上的各个模块无法像之前那样通过内存寻址的方式来互相访问,而是需要通过网络来进行通信。

Gefangenes的博客 829

三连杆平面机器人的动力学

0.前言 在这个例子中推导并实现三连杆平面机器人的运动方程。特别的,这里使用拉格朗日法推导运动方程。系统模型如下: 其中在枢轴点处Tm为驱动力矩【一般由伺服电机提供】; b*theta_d:为粘性阻尼扭矩 1、系统方程符号推导前--简介 首先明确欧拉-拉格朗日运动方程: 同样也可以根据作用在多体系统上的非保守力和非保守扭矩来定义广义力Qk。 作用在系统上的广义力的公式为: 其中: Qk:是与广义坐标关联的广义力 Nf_nc :是作用的非保守力的数量 Nt_nc:是作用的非保守扭矩的.

weixin_39090239的博客 4930

花了快2个月自己动手写了一个简单的RPC框架

举个例子我们的系统中的某个服务的访问量特别大,我们将这个服务部署在了多台服务器上,当客户端发起请求的时候,多台服务器都可以处理这个请求。最初的是时候,我是基于传统的 BIO 的方式 Socket 进行网络传输,然后利用 JDK 自带的序列化机制 以及内存直接存储相关服务相关信息来实现这个 RPC 框架的。实现一个简单的 RPC 框架实际是比较容易的,不过,相比于手写 AOP 和 IoC 还是要难一点点,前提是你搞懂了 RPC 的基本原理。注册中心 :注册中心首先是要有的,推荐使用 Zookeeper。

代码界的扛把子 320

基于STM32设计的太阳能智慧路灯_444

本文设计并实现了一种基于 STM32 的太阳能智慧路灯系统。系统以 STM32F103C8T6 单片机为核心,集成温湿度检测、空气质量检测、环境光照检测、行人检测和路灯故障检测等功能,实现对路灯运行环境和工作状态的实时感知。

462

机器人的“大脑”进化论:从专用控制器到高性能SoC的异构计算时代

摘要:随着AI与机器人技术融合,高性能芯片成为机器人智能化的关键。本文分析了机器人对芯片的核心需求,包括多模态数据处理、实时控制和智能决策能力。系统级芯片(SoC)因集成CPU、GPU/NPU等模块而成为主流选择。市场呈现分层格局:中低端设备(如扫地机器人)采用"MCU+轻量SoC"方案,满足基础功能;高端机器人则依赖"高性能SoC+独立GPU"处理复杂任务。除主控芯片外,完整的机器人系统还需传感器接口、驱动、通信等配套芯片。未来,芯片技术的进步将持续推动机器人智能化

致力于lidar应用开发 83

从0到1开发一个简单的RPC框架

RPC就是远程过程调用,在工作中很多需求背景都会有多个服务器,有服务器A、服务器B、服务器C。有时候就会需要服务器B调用服务器A上的某个方法,这时候就需要用到RPC了。市面上也有很多成熟的RPC框架,在我国常用的就是Dubbo。因为它有比较好的社区动态,也有比较成熟的案例项目。Dubbo、Motan、gRPC、Thrift,这四种是比较常见的RPC框架RPC开发商生态/社区活跃度适配语言Dubbo阿里√Motan新浪×JavagRPCGoogle√Thrift。

开开心心,努力生活 848

2 硬件工程师笔面试高频知识考点真题解析——电容

本文全面解析了电容在电子电路中的关键应用与技术要点。主要内容包括:1. 电容选型核心要素:介质材质(陶瓷/电解/钽电容等)、容值精度、耐压等级、温度特性、ESR参数等,不同应用场景(滤波/去耦/谐振等)的选型策略。2. 典型电路应用原理:详细阐述去耦电容布局规则、晶振负载电容作用、共射放大电路旁路电容功能,以及RC电路的滤波/定时等应用。3. 特殊问题解决方案:MLCC啸叫机理与对策、寄生电容影响与消除、高速信号线电容使用禁忌等工程实践难题。4. 安全规范要点:X/Y电容的区别与选用、电解/钽电容防反接措施

XU157303764的博客 1561

如何实现一个简单的rpc框架

一、RPC简介 RPC,全称为Remote Procedure Call,即远程过程调用,它是一个计算机通信协议。它允许像调用本地服务一样调用远程服务。它可以有不同的实现方式。如RMI(远程方法调用)、Hessian、Http invoker等。另外,RPC是与语言无关的。     RPC示意图 如上图所示,假设Computer1在调用sayHi()方法,对于Comp

joenqc的博客 5779

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

动手实现一个简单的RPC框架

    RPC(Remote Procedure Call,远程过程调用)一般用来实现部署在不同机器上的系统之间的方法调用,是的程序能够像访问本地资源一样,通过网络传输去访问远端系统资源。RPC框架实现的架构原理都是类似的,如下图所示。                    Client Code:客户端调用方代码,负责发起RPC调用,为调用方提供接口    Serialization:负责对RP...

yanghan1222的博客 2342

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

JAVA从零手写实现一个简单RPC框架

JAVA手写实现一个简单RPC框架菜鸟笔记场景模拟假设客户端(用户逻辑服务)服务端(数据查询服务)运行结果 菜鸟笔记 RPC-远程过程调用 主要用于解决分布式系统中,服务之间的调用问题。远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑 例如:在实际后台开发中,开发者A负责数据查询服务,开发者B负责用户逻辑服务,那么开B需要调用A的用户数据查询服务,所以A.B需要有一个共同约定协...

belief7753的博客 2744

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java实现一个简单RPC框架

Java实现一个简单RPC框架什么是RPC框架为什么还要使用远程调用?使用主要技术项目结构图代码 什么是RPC框架 RPC(Remote Procedure Call),顾名思义,指的是远程过程(方法)调用,与之相对应的就是本地方法调用。 本地方法调用: 放到具体的代码中,可以理解为,被调用方(producer)和调用方(consumer)在同一个项目当中。 远程方法调用: 放到具体的代码中,...

蒋蒋 460

Java实现一个简单的RPC框架(一) 本地调用

参考: crylearner专栏  一个简单的RPC框架是如何炼成的 :http://blog.youkuaiyun.com/crylearner/article/details/46898537 什么是RPC: 其实就是我把参数传给你,你处理完之后把返回值回传给我。只不过双方不在同一台机,这就是所谓的“远程过程调用”,简称RPC。 rpc框架做的最重要的一件事情就是封装,调用

赞美月亮的专栏 2676

一个简单的RPC框架代码实现

Java代码 /* * Copyright 2011 Alibaba.com All right reserved. This software is the * confidential and proprietary information of Alibaba.com ("Confidential * Information"). You shall not disclose ...

疯一样的女子 278

自己实现一个简单的RPC框架

RPC的全称是Remote Procedure Call,它是一种进程间的通信方式。允许像调用本地服务一样调用远程服务。

清涵 2832

golang实现一个简单的rpc框架

RPC在分布式系统中经常使用,这里写一个简单的demo实践一下。

andy dennis的博客 725

基于Protobuf实现一个简单的RPC框架

文章目录1、Proto定义RPC服务1.1 编写proto文件1.2 使用protoc工具生成RPC对象接口模型2、编写RPC服务逻辑3、编写RPC服务框架3.1 RpcServer3.2 构造数据包,方便识别service和method信息3.3 RpcServer启动主程序4、编写RPC客户端代码5、编写客户端使用样例6、RPC服务框架中类图7、RPC调用链路 使用Protobuf实现RPC框架大致可以分为以下几步: 1、编写proto文件定义服务,并使用Protoc工具生成RPC对象接口模型。 2、编

TABE_的博客 2299

【手写实现一个简单版的Dubbo,深刻理解RPC框架的底层实现原理】

在以前都是单体应用的年代,是不需要RPC框架的,那时候还不知道RPC是什么,所有的数据都是来自于本地的数据库,然后全都是本地的方法调用。但是随着业务的发展,访问量的不断增加,原先的单体应用已经不能满足需求,于是要做应用拆分,原先的单体应用被拆成了多个服务,然后就出现了服务间调用的问题。这样复杂度就一下子上来了,如何解决服务间调用的问题呢?我们可以自己写代码,通过http的方式去访问对方,或者通过Socket连上对方的系统进行通信,发送调用的方法名和调用参数等信息。

weixin_43889578的博客 1325

实现一个简单的rpc框架——simple-rpc

代码链接 https://github.com/yutian1999/simple-rpc rpc-server rpc服务端 服务的提供者依赖此模块 rpc-client rpc客户端 服务的调用者依赖此模块 rpc-common 公共模块 demo provider-demo 服务提供者示例 consumer-demo 服务调用者示例 技术分析 rpc远程调用的本质是对引用的依赖进行代理底层偷偷进行远程调用。 技术依赖 netty (通信,进行远程调用 cglb (代理,对本地方法调用代理

yutian_1999的博客 464

【远程调用框架】如何实现一个简单的RPC框架(一)想法与设计

【如何实现一个简单的RPC框架】系列文章:【远程调用框架】如何实现一个简单的RPC框架(一)想法与设计 【远程调用框架】如何实现一个简单的RPC框架(二)实现与使用 【远程调用框架】如何实现一个简单的RPC框架(三)优化一:利用动态代理改变用户服务调用方式 【远程调用框架】如何实现一个简单的RPC框架(四)优化二:改变底层通信框架 【远程调用框架】如何实现一个简单的RPC框架(五)优化三:软

吃货小跟班的博客 1万+

简简单单实现一个mini版RPC框架

title: 简简单单实现一个mini版RPC框架 comments: false toc: true categories: 分布式方案 tags: RPC框架 MiniRPC date: 2021-01-06 23:31:58 所谓的RPC,是指Remote Procedure Call(远程过程调用),让我们可以调用本地的函数一样去调远程函数。 RPC可以屏蔽远程调用跟本地调用的区别,让我们感觉就是调用项目内的方法。 RPC隐藏底层网络通信的复杂性,让我们更专注于业务逻辑。 RPC的原理 .

ksisn的博客 556
下一篇: sed 和awk常用命令集合备忘
韩慕灵
博客等级 码龄15年 8粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值