网站收录查询apiwordpress主题video
网站收录查询api,wordpress主题video,企业运营管理论文,小米官网首页文 / Kenyon#xff0c;资深软件架构师#xff0c;15年软件开发和技术管理经验#xff0c;从程序员做到企业技术高管#xff0c;专注技术管理、架构设计、AI技术应用和落地。由于公众号推流的原因#xff0c;请在关注页右上角加星标#xff0c;这样才能及时收到新文章的推…文 / Kenyon资深软件架构师15年软件开发和技术管理经验从程序员做到企业技术高管专注技术管理、架构设计、AI技术应用和落地。由于公众号推流的原因请在关注页右上角加星标这样才能及时收到新文章的推送。引言在上一篇文章中我们基于架构设计原则设计了RPC框架的基础架构。今天我们将进入实战阶段实现RPC框架的核心功能包括服务代理、序列化、网络通信等模块。在实现过程中我们将重点展示如何将SOLID原则、高内聚低耦合、KISS等架构设计原则应用到实际代码中。一、核心组件的实现1. 序列化模块Serializer遵循开闭原则我们设计了Serializer接口并提供了JSON实现// 序列化接口支持扩展不同的序列化方式publicinterfaceSerializer{/** * 将对象序列化为字节数组 * * param obj 要序列化的对象 * param T 对象类型 * return 序列化后的字节数组 * throws Exception 序列化异常 */Tbyte[]serialize(Tobj)throwsException;/** * 将字节数组反序列化为对象 * * param bytes 序列化后的字节数组 * param clazz 对象类型 * param T 对象类型 * return 反序列化后的对象 * throws Exception 反序列化异常 */TTdeserialize(byte[]bytes,ClassTclazz)throwsException;/** * 序列化类型枚举 */enumType{//目前暂时只是支持JSON后续可以在这里添加要支持的其他序列化方式JSON(1);privatefinalintcode;Type(intcode){this.codecode;}publicintgetCode(){returncode;}/** * 根据code查找对应的序列化类型 * * param code 序列化类型码 * return 序列化类型 */publicstaticTypefindByCode(intcode){for(Typetype:Type.values()){if(type.codecode){returntype;}}returnJSON;// 默认使用JSON}}}// JSON序列化实现publicclassJsonSerializerimplementsSerializer{privatestaticfinalObjectMapperobjectMappernewObjectMapper();OverridepublicTbyte[]serialize(Tobj)throwsException{if(objnull){returnnewbyte[0];}returnobjectMapper.writeValueAsBytes(obj);}OverridepublicTTdeserialize(byte[]bytes,ClassTclazz)throwsException{if(bytesnull||bytes.length0){returnnull;}returnobjectMapper.readValue(bytes,clazz);}}2. 网络传输模块Transport基于单一职责原则我们将网络传输模块拆分为客户端和服务端// 网络传输客户端接口publicinterfaceTransportClient{voidconnect(InetSocketAddressaddress);byte[]send(byte[]data)throwsException;voidclose();}// 网络传输服务端接口publicinterfaceTransportServer{voidstart(intport,RequestHandlerhandler);voidstop();intgetPort();}// 请求处理器接口publicinterfaceRequestHandler{byte[]handle(byte[]request);}// 使用Netty实现的传输客户端publicclassNettyTransportClientimplementsTransportClient{privatestaticfinalLoggerloggerLoggerFactory.getLogger(NettyTransportClient.class);privatestaticfinalintDEFAULT_CONNECT_TIMEOUT5000;privateChannelchannel;privateEventLoopGroupgroup;privateResponseHandlerresponseHandler;Overridepublicvoidconnect(InetSocketAddressaddress){groupnewNioEventLoopGroup();BootstrapbootstrapnewBootstrap();try{bootstrap.group(group).channel(NioSocketChannel.class).option(ChannelOption.CONNECT_TIMEOUT_MILLIS,DEFAULT_CONNECT_TIMEOUT).option(ChannelOption.TCP_NODELAY,true).handler(newChannelInitializerSocketChannel(){OverrideprotectedvoidinitChannel(SocketChannelch)throwsException{ChannelPipelinepipelinech.pipeline();// 处理粘包问题pipeline.addLast(newLengthFieldBasedFrameDecoder(65535,0,4,0,4));pipeline.addLast(newLengthFieldPrepender(4));// 字节数组编解码器pipeline.addLast(newByteArrayDecoder());pipeline.addLast(newByteArrayEncoder());// 客户端处理器NettyClientHandlerclientHandlernewNettyClientHandler();pipeline.addLast(clientHandler);}});// 连接服务端ChannelFuturefuturebootstrap.connect(address).sync();this.channelfuture.channel();// 初始化响应处理器responseHandlernewResponseHandler();// 设置客户端处理器的响应处理器((NettyClientHandler)channel.pipeline().last()).setResponseHandler(responseHandler);}catch(Exceptione){logger.error(Failed to connect to server: {},address,e);thrownewRuntimeException(Failed to connect to server: address,e);}}Overridepublicbyte[]send(byte[]data)throwsException{if(channelnull||!channel.isActive()){thrownewIllegalStateException(Channel is not connected);}// 发送数据channel.writeAndFlush(data).addListener((ChannelFutureListener)future-{if(!future.isSuccess()){Throwablecausefuture.cause();if(causeinstanceofException){responseHandler.setException((Exception)cause);}else{responseHandler.setException(newRuntimeException(cause));}}});// 等待响应returnresponseHandler.waitForResponse();}Overridepublicvoidclose(){if(channel!null){channel.close();}if(group!null){group.shutdownGracefully();}}/** * 客户端处理器 */privatestaticclassNettyClientHandlerextendsSimpleChannelInboundHandlerbyte[]{privatestaticfinalLoggerloggerLoggerFactory.getLogger(NettyClientHandler.class);privateResponseHandlerresponseHandler;OverrideprotectedvoidchannelRead0(ChannelHandlerContextctx,byte[]msg)throwsException{if(responseHandler!null){responseHandler.setResponse(msg);}}OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause)throwsException{logger.error(Exception in Netty client handler,cause);if(responseHandler!null){if(causeinstanceofException){responseHandler.setException((Exception)cause);}else{responseHandler.setException(newRuntimeException(cause));}}ctx.close();}publicvoidsetResponseHandler(ResponseHandlerresponseHandler){this.responseHandlerresponseHandler;}}/** * 响应处理器 */privatestaticclassResponseHandler{privatefinalCountDownLatchlatchnewCountDownLatch(1);privatebyte[]response;privateExceptionexception;publicbyte[]waitForResponse()throwsException{if(!latch.await(30,TimeUnit.SECONDS)){thrownewRuntimeException(Request timeout);}if(exception!null){throwexception;}returnresponse;}publicvoidsetResponse(byte[]response){this.responseresponse;latch.countDown();}publicvoidsetException(Exceptionexception){this.exceptionexception;latch.countDown();}}}3. 服务代理模块Service Proxy使用迪米特法则代理模块只与必要的组件通信// RPC客户端核心类publicclassServiceProxyimplementsInvocationHandler{privatestaticfinalLoggerloggerLoggerFactory.getLogger(ServiceProxy.class);// 服务接口类privatefinalClass?serviceClass;// 服务注册中心privatefinalRegistryCenterregistryCenter;// 负载均衡策略privatefinalLoadBalanceloadBalance;/** * 构造函数 * * param serviceClass 服务接口类 * param registryCenter 服务注册中心 */publicServiceProxy(Class?serviceClass,RegistryCenterregistryCenter){this(serviceClass,registryCenter,newRandomLoadBalance());}/** * 构造函数 * * param serviceClass 服务接口类 * param registryCenter 服务注册中心 * param loadBalance 负载均衡策略 */publicServiceProxy(Class?serviceClass,RegistryCenterregistryCenter,LoadBalanceloadBalance){this.serviceClassserviceClass;this.registryCenterregistryCenter;this.loadBalanceloadBalance;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{// 创建RPC请求的对象把调用的服务接口类、方法名、参数类型、参数值等信息封装到请求对象中RpcRequestrequestnewRpcRequest();request.setRequestId(UUID.randomUUID().toString());request.setServiceName(serviceClass.getName());request.setMethodName(method.getName());request.setParameterTypes(method.getParameterTypes());request.setParameters(args);logger.debug(Sending RPC request: {}, service: {}, method: {},request.getRequestId(),request.getServiceName(),request.getMethodName());// 从注册中心获取服务地址列表ListInetSocketAddressaddressesregistryCenter.discover(serviceClass.getName());if(addressesnull||addresses.isEmpty()){thrownewRuntimeException(No service available for: serviceClass.getName());}// 使用负载均衡策略选择服务地址InetSocketAddressaddressloadBalance.select(serviceClass.getName(),addresses);if(addressnull){thrownewRuntimeException(No service address selected for: serviceClass.getName());}logger.debug(Selected service address: {},address);// 创建客户端并发送请求这里暂时使用Netty作为网络传输组件TransportClientclientnewNettyTransportClient();try{// 创建序列化器这里暂时使用JSON序列化后续可以添加其他序列化方式并且改成读取配置的方式来确定使用哪种序列化方式SerializerserializernewJsonSerializer();// 连接到服务端client.connect(address);// 序列化请求byte[]requestDataserializer.serialize(request);// 发送请求并获取响应数据byte[]responseDataclient.send(requestData);// 反序列化响应RpcResponseresponseserializer.deserialize(responseData,RpcResponse.class);if(response.isSuccess()){returnresponse.getResult();}else{thrownewRuntimeException(RPC call failed: response.getError());}}finally{client.close();}}}二、架构设计原则的应用总结在上面代码实现的过程中我们分别应用了以下架构设计原则1. SOLID原则比如每个组件都只是负责一个明确的功能这就很好符合了单一职责原则然后涉及到后续可能要调整或者扩展到地方我们都是通过面向接口的编程然后再通过实现接口的方式来实现组件的可扩展这样就很好地应用了开闭原则和里氏替换原则在编写接口的时候我们也遵循了接口隔离原则和里氏替换原则即每个组件都有自己的接口而且接口只包含必要的方法然后组件接口的实现类可以随时替换父类的实现而不会影响到程序的正常运行。最后我们使用其他模块的时候依赖都是依赖接口然后再通过构造函数的方式来注入具体的实现类这样高层模块就不需要依赖底层模块从而做到了依赖倒置原则。2. 通用设计原则在实现RPC框架的过程中我们也应用了多个通用设计原则我们在代码的实现过程中非常注重代码的简洁基本都是做最基础的设计和实现避免了过度设计实现的过程中也只实现当前必要的核心功能确保代码的可读性和可维护性同时也考虑到了代码的性能和扩展性这就很好地体现了KISS原则。我们设计和实现的每个组件内部的功能都紧密相关的高内聚而组件之间基本都是通过抽象接口来进行通信减少跟实现模块或者代码的直接依赖低耦合这样的设计使得各组件可以独立演化和维护这就是高内聚低耦合原则的应用。在模块和组件之间我们遵循只与直接朋友通信的原则组件之间只与直接依赖的组件进行交互避免形成复杂的依赖链提高系统的稳定性这就是迪米特法则的应用。然后我们通过业务的抽象和代码复用的机制避免了出现大量代码重复的情况例如通过统一的接口定义实现不同组件的复用降低了维护成本这个就是DRY原则的应用。三、总结与下一步计划因为篇幅的问题在这篇文章就先写这么多文章中我们实现了整个RPC框架里面最核心的组件包括了序列化模块、网络传输模块和服务代理模块。在实现的过程中我们重点展示了如何将架构设计原则应用到实际代码中确保代码的可扩展性、可维护性和灵活性。在下一篇文章中我们将会完成这个RPC框架的剩余功能像服务注册与发现、服务端核心的实现、客户端的负载均衡等模块并编写相关的测试用例来进行完整的测试。同时也会把项目的代码一起放上来给大家观摩和吐槽。互动话题在实现RPC框架的过程中你认为哪个组件的设计最具挑战性为什么欢迎在评论区分享你的观点。关于作者Kenyon资深软件架构师15年的软件开发和技术管理经验从程序员做到企业技术高管。多年企业数字化转型和软件架构设计经验善于帮助企业构建高质量、可维护的软件系统目前专注技术管理、架构设计、AI技术应用和落地全网统一名称六边形架构欢迎关注交流。原创不易转载请联系授权如果觉得有帮助请点赞、收藏、转发三连支持