1:spring http Design Ideas
Recently in the study of the company's own set of RPC Remote call framework, see its internal implementation of the design idea relies on the idea of the remote invocation of spring, so idle to nothing, just want to learn under, and record.
As the implementation of the spring remote call, the simplest should be through the implementation of HTTP calls, in which dependencies are not dependent on third-party related components, the caller only need to configure the relevant HTTP protocol
Can be implemented, simple configuration, you can use the spring of the IOC container bean definition and so on the idea to call, simple, convenient, no need to write more HTTP-related code,
More suitable for calls between internal communication systems.
In the daily development, often encounter a variety of internal system communication between calls, in fact, can use the following several design methods. However, the simplest should be the HTTP mode that comes with spring and then encapsulate it yourself
Packaged as a client jar and so on, a common client call
In fact, in the daily invocation implementation, there are several kinds of design can be done between the client and the service side of the call, such as
Ali's DB middleware is using a similar mode of communication, but has not studied
Internal use is the following way to communicate, you can monitor the software to track the Q, in the processing of large data high concurrency, good q middleware and Java packaging asynchronous processing, to solve the database and all aspects of the bottleneck pressure, but there are shortcomings, the various applications between the transaction is uncontrollable, Can only be processed by ex post compensation. Overall, it's a good design.
Let's talk about the Springhttp agreement first.
2: Client
Httpinvokerproxyfactorybean is designed in the client, which is a proxy factory bean (Proxyfactorybean) that uses spring AOP to encapsulate the client of the HTTP caller, since AOP is used. The proxy object is used, and the appropriate interceptor is set for the proxy method. Httpinvokerproxyfactorybean, through Afterpropertiesset to initiate the establishment of remote call infrastructure, etc., Proxy interceptor Httpinvokerclientinterceptor, The basic implementation of the client is encapsulated in Httpinvokerclientinterceptor, such as the HTTP request link, Request object serialization, request delivery to the server, and, when the interceptor is received, it will also send an HTTP response back to the terminal. And the object returned from the server side of the remote call to the application to use, complete an HTTP request basic implementation.
The HTTP invoker is a remote invocation scheme based on the HTTP protocol, using the HTTP caller and the same basic configuration module as the Java RMI
Httpinvokerproxyfactorybean specific implementations such as inherit the Factorybean, use Httpinvokerproxyfactorybean need to set the corresponding bean to the agent factory configuration
Set the URL address of the remote service, set the interface of the Terminal service, and then set the Agent factory to the Remoteservice property of the client application bean, with this setting, the client application configuration is configured so that it can enjoy the remote service as local.
<BeanID= "Proxy"class= "Org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"> < Propertyname= "serviceurl">Http://localhost:8080/xxxx/xxx</ Property><!--the requested server-side URL - < Propertyname= "Serviceinterface">com.abc.cc.ddd.ee</ Property><!--specific service-side invocation interface path -</Bean><BeanID= "Test"class= "Abc.sss.ssss"> < Propertyname= "Remoteservice"ref= "Proxy"/> <!--introduced into the agent factory -</Bean>
Httpinvokerproxyfactorybean in the package corresponding to the remote service information, domain name, port, service URL, these are the remote service calls required information, and because of the use of httpinvoker, so in the URL specified protocol is the HTTP protocol, For clients accessing the remote service invocation, it is convenient to use the remote call as long as the proxy object provided by the Httpinvokerproxyfactorybean is used, as well as local, remote call to send the data communication and remote service interaction, are encapsulated by proxy proxies, which are transparent to the client, which are mainly packaged in Httpinvokerproxyfactorybean.
It can be known from the graph that when the service is started, the system automatically initializes the proxy object inside the spring container and automatically executes the Afterpropertiesset related method
How does the Httpinvokerproxyfactorybean encapsulate and transfer data to the server?
Public classHttpinvokerproxyfactorybeanextendsHttpinvokerclientinterceptorImplementsFactorybean<object> { PrivateObject Serviceproxy; //code eliminates a number of code to omit some code to omit several @Override Public voidAfterpropertiesset () {//initialization performs HTTP configuration loading, etc. to prepare for subsequent delivery to the server Super. Afterpropertiesset (); //gets the interface that is configured on the client, determines whether the interface is configured, the parent class here carries out the load configuration of the class, etc.//here, not a configuration, but a specific interface class if(Getserviceinterface () = =NULL) { Throw NewIllegalArgumentException ("Property ' Serviceinterface ' is required"); } //The relevant parameters, the corresponding class load information, and the specific client implementation class proxy are specified This. Serviceproxy =NewProxyfactory (Getserviceinterface (), This). GetProxy (Getbeanclassloader ()); } PublicObject GetObject () {return This. Serviceproxy; } PublicClass<?>Getobjecttype () {returnGetserviceinterface (); } Public BooleanIssingleton () {return true; }}
Proxyfactory the Invoke method executed in the Httpinvokerclientinterceptor interceptor specified by the
//the method that the specific call executes PublicObject Invoke (Methodinvocation methodinvocation)throwsThrowable {if(Aoputils.istostringmethod (Methodinvocation.getmethod ())) {return"HTTP invoker proxy for service URL [" + getserviceurl () + "]"; } //Create the parameter information needed for the remote service, such as spring's own implementation, create a factory, etc.remoteinvocation invocation =createremoteinvocation (methodinvocation); Remoteinvocationresult result; Try { //Call the service side, send the requestresult =executerequest (invocation, methodinvocation); } Catch(Throwable ex) {ThrowConverthttpinvokeraccessexception (ex); } Try { //The objects needed to return information to the server, etc. returnRecreateremoteinvocationresult (Result); } Catch(Throwable ex) {if(Result.hasinvocationtargetexception ()) {Throwex; } Else { Throw NewRemoteinvocationfailureexception ("Invocation of method [" + Methodinvocation.getmethod () + "] Faile D in HTTP invoker remote service at ["+ getserviceurl () +"] ", ex); } }}
Main operations in the above code: encapsulation of the sent interface, etc.
Remoteinvocationfactory >> createremoteinvocation (methodinvocation methodinvocation);
Remoteinvocation >> (remoteinvocation (String methodName, class[] parametertypes, object[] arguments))
Defaultremoteinvocationfactory >> createremoteinvocation (methodinvocation methodinvocation)
/** * Create A new remoteinvocation for the given AOP method invocation. @param methodinvocation the AOP invocation to convert */
remoteinvocation >> (remoteinvocation (String methodName, class[] parametertypes, object[] arguments)) concrete Is
Publicremoteinvocation (methodinvocation methodinvocation) { This. MethodName =Methodinvocation.getmethod (). GetName (); This. parametertypes =Methodinvocation.getmethod (). Getparametertypes (); This. Arguments =methodinvocation.getarguments (); Execute send httpinvokerrequestexecutor-->>Abstracthttpinvokerrequestexecutor classSpecific Implementation
Public FinalRemoteinvocationresult executerequest (
Httpinvokerclientconfiguration config, remoteinvocation invocation)throwsException {
Bytearrayoutputstream BAOs=Getbytearrayoutputstream (invocation);
if(logger.isdebugenabled ()) {
Logger.debug ("Sending HTTP invoker request for service at [" + config.getserviceurl () +
"], with size" +baos.size ());
}
returnDoexecuterequest (config, BAOs);
}
The specific flowchart is as follows:
Client request Configuration Send request
3: Service Side
The Httpinvokerserviceexporter is designed on the server side, and the remote service object is exported through Serviceexporter, because it needs to process the HTTP request, so it needs to rely on the SPRINGMVC module to implement, Encapsulates the dispatchservlet of the MVC framework and sets the appropriate controller. The controller performs the corresponding HTTP request processing, such as receiving a service request, deserializing the service request object, handing over the request to the server object, and finally returning the resulting result through the HTTP protocol to the client via serialization.
Server-side configuration:
<BeanID= "HelloService"class= "Com.logcd.server.service.impl.HelloService"/> <Beanname= "/xxxservice"class= "Org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"Lazy-init= "false"> < Propertyname= "Service"> <refBean= "Xxxservice"/> </ Property> < Propertyname= "Serviceinterface"> <value>com.abc.cc.ddd.ee</value> </ Property> </Bean>
How does the server-side receive for spring HTTP respond? The main use of Httpinvokerserviceexporter
Public voidHandleRequest (httpservletrequest request, httpservletresponse response)throwsservletexception, IOException {Try { //encapsulates the request object, converting it to a remote call objectremoteinvocation invocation =readremoteinvocation (Request); //executes the request and creates the returned objectRemoteinvocationresult result =Invokeandcreateresult (Invocation, GetProxy ()); //Return to clientWriteremoteinvocationresult (Request, response, result); } Catch(ClassNotFoundException ex) {Throw NewNestedservletexception ("Class not found during deserialization", ex); } }
Executes the logic of the Code and returns, here the code is as follows
remoteinvocation Public object Invoke (Object TargetObject) throws nosuchmethodexception, Illegalaccessexception, invocationtargetexception { = Targetobject.getclass (). GetMethod (this. parametertypes); return This . arguments); }
Write back to Client
Httpinvokerserviceexporterprotected voidWriteremoteinvocationresult (httpservletrequest request, httpservletresponse response, Remoteinvocationres Ult result, OutputStream OS)throwsIOException {objectoutputstream oos=Createobjectoutputstream (Decorateoutputstream (Request, Response, OS)); Try{Dowriteremoteinvocationresult (result, oos);//Call the parent class Remoteinvocationserializingexporter } finally{oos.close (); }} remoteinvocationserializingexporterprotected voidDowriteremoteinvocationresult (remoteinvocationresult result, ObjectOutputStream oos)throwsIOException {oos.writeobject (result); }
The flowchart of the server-specific execution code is as follows:
Specifically, the entire spring HTTP remote call ended, in fact, in development, if you want to encapsulate similar remote calls, can be modeled after the development of Springhttp mode, the HTTP into the other protocol, you can achieve
Implementation of the Spring Remote Call implementation-spring HTTP invocation