1. Background
Lina solves the problem under the current Jar pack call (slow startup, high coupling, dependent transmission, memory consumption and so on, the original program in a virtual machine, dispersed into a number of different virtual machines running, the original system into a distributed service system.
The first issue of online reviews This service uses Lina to publish the service. Lina please refer to (Http://wiki.koubei.com/index.php/Rd/HuoNiao/Lina) for detailed instructions.
After using it I think Lina has the following advantages: The RMI protocol is encapsulated in a transparent way, and the service can be invoked by using spring's Factroybean client only to care about the exposed service names of the interfaces and services invoked on the server side. Using the Monitor module, the AOP method is used to graft into the original system, and the system can be viewed visually and instantaneously when the systems are running. In addition, the relevant code mentioned in this article, if you want to see the source code, you can send me an email to request baisui@taobao.com 2. Question
After experiencing these advantages, still feel the following deficiencies, feel there is room for improvement. 2.1. Configure an export agent factory for each service object <!--class fixed--> <bean id= "Leavewordrmiserver" class= " Org.springframework.remoting.rmi.RmiServiceExporter "> <!--corresponding business package implementation service--> <property name=" service "><ref bean=" Leavewordrmiservice/></property> <!--service Name, consistent with client-defined service name--> <property " ServiceName "><value>lwt</value></property> <!--Business interface--> <property name=" Serviceinterface "><value>com.koubei.leaveword.client.rmi.ileavewordrmiserver</value></ Property> <!--listening port, fixed--> <property name= "Registryport" ><value>7071</value></ Property> <!--Interceptor, fixed--> <property name= "interceptors" ><list><ref bean= "MonitorAdvisor"/ ></list></property> </bean>
Each outward-exposed service needs to be configured with such a Rmiserviceexporter proxy object that the objects in the IOC container will be published with the help of the Rmiserviceexporter service as RMI, yes, this is correct. However, when one day in the future due to performance considerations need to expose the services in other ways, such as the use of the Hession protocol, or the same service needs to be hession and RMI two protocols to open the service, then, if the use of the existing way to deploy the words need to be modified. Obviously, a lot of the original configuration needs to be modified. 2.2. Simplify client invocation distributed service approach
Now that the Lina distributed service is invoked on the client, a server-side proxy object needs to be configured in spring, the following is an example <bean id= "leavewordconf" class= Com.koubei.rpc.client.conf.RmiProtocolConf "> <!--server address--> <property name=" Server Value= " Leaveword.pr.vip.hz1.koubei.com "/> <!--server port--> <property name=" Port "value=" 7071 "/> <!--call Timeout in units: milliseconds), can not fill in, default 3000--> <property name= "invoketimeout" value= "3000"/> < check the connection at startup, do not fill, default false--> < Property Name= "Lookupstubonstartup" value= "false"/> < refresh stub when failed!--, default true--> <property " Refreshstubonconnectfailure "value=" true "/> <!--cache stub (performance impact), not filled, default true--> <property name=" Cachestub " Value= "true"/> </bean>
The configuration of the client also has a potential risk: need for each service, configure the corresponding client configuration, so that the client's configuration is also very large, if the same service in n places there is a call need to configure N if the service side of the service configuration information has changed a day, Then you have to look up all the client configurations and modify them one by one, which is a very tedious and error-prone job . 2.3 Each service is a separate service name for the client, so that there is a potential risk of server-side maintenance monitoring.
You can change the way services are communicated in a different form:
3. Perfect 3.1. Summary of issues: for each server-side service, the caller configures a spring configuration file. This will be more cumbersome to maintain later. The publishing process can be cumbersome and error-prone. The server side and the client are separate transports without a unified gateway. 3.2. The idea of improvement: server-side bean configuration problem: To solve these problems, you can take advantage of MAVEN's powerful plug-in capabilities, let Maven from the dynamic generation of these configuration server-side configuration files, at the time of publishing server-side jar package, You can automatically generate proxy files for server-side beans, and, when packaged, you can automatically hit a jar package with a previously generated configuration file, in which the user simply knocks out some MAVEN commands. Client XML configuration issues: The client is configured with a profile for each service invocation because the client calls without knowing where the service it can invoke, on which server, what the IP is, what the port is, what the service name is, so these must be set up in advance on the caller side, This allows the client to load the server-side configuration normally with the client's configuration after it is started. Therefore, you can add a service center service, when the server is started, the IP address of the service, service name, service port to the service center of the database. The development package that the client relies on is simply the Pojo object on which the service interfaces and service interfaces in the jar package in the server-side deployment package are based, and you can develop a MAVEN plugin to generate a client-side dependency package at the package stage of the Maven run. This is the only way to call this client package when the client is deployed. Transformed into such a communication mode, the client and server-side communication can be communicated through the unified gateway, in the original mode of communication under the Monitor module is through AOP to the original system, the existing architecture in the monitor module can not be configured through AOP, This will improve the efficiency of the system. 3.3. Client Invocation method Improved
For the client, the service object that the action relies on can only be found through the Findservice () method of the Servicelookup class, and does not need to care about the server IP address port on which the service resides.
The following is a sequential diagram of the modified client Lookup server-side call:
As pictured above, the main process for finding service-side webwork is as follows: WebWork invokes the Invoke function of Actioninvocation, Call the Distributeserviceinjectinterceptor interceptor in the order in which the Interceptor is configured (the interceptor's role is to inject the distributed service for the target action) Distributeserviceinjectinterceptor uses the mechanism of reflection to find the injection point of myaction distributed services. public class Useraction extends Actionsupport {public String execute () throws exception{return SUCCESS;} @Inject Public void Setuserservice (UserService userservice) {this.userservice = UserService;}}
A @inject identification is made on the set method of the JavaBean that needs to be injected into the distributed service, so Distributeserviceinjectinterceptor will find that the action has a distributed service usage requirement. It then invokes the Lookupservice Findservice method to find the desired service object and injects the service object into the action. 3.4.LookupService
The following is a class diagram of the class related to Lookupservice:
When Servicelookup initializes, the JGroups Jchannel object is used to register servicelookup as a member of the group in the JGroups group. Events in distributed services are monitored in real time during the Servicelookup lifecycle. For example, when a new service node is added to a distributed group, or a service node is offline. Such changes require the automatic updating of the cached service information (the IP, port, service name) of the Servicelookup object in each service invocation side. Jgroup assumes the function of distributing messages in distributed systems. 3.5. Network structure Diagram
As shown in the figure above, there are three parts of the system, the first part is the service delivery server, the second part is the database server that holds the service metadata information, and the third part is the calling end of the call service.
The following is a description of the process in which the service is published to the service invocation service: one server in the Distributed Service system cluster There are some new services that need to be online, first the server initializes the objects in this virtual machine. Publish the service in your own server, the port that the service is in, to the service center's database. Initializes a Jchannel object into the Jgroup of the distributed service in this virtual machine and broadcasts a message to the group that updates the waiter's data. Each client caller receives the updated message from the cluster and deletes the original information in the machine. The client caller reloads the new service metadata information in the service center. 3.6. Create a service object
Based on the above considerations, we need to make some minor changes to the existing subcontracting code. The following changes need to be adapted to the new Distributed service transformation:
During the development process, you need to identify the interfaces that you want to publish services to externally. For example, in the development of the "Free Shop Listings Association" interface, you need to use Com.koubei.lina.ext.Service Annotation Identification Service interface, as follows: On the service interface with the @service tag, This interface is automatically bound to the pre-set port for outward release during late initialization. The sample code is as follows:
Import com.koubei.dian.pojo.DianAssociation; Import Com.koubei.lina.ext.Service; /** * FREE ONLINE STORE Listings Association * * @Service Public interface Idianassociationservice {boolean insertdianassociation (dianassociation DianA Ssociation);
By identifying @service on the Idianassociationservice service interface, you have the following effects: Initializing the needs of spring
When the virtual machine is initialized, it knows that the service object that implements this interface needs to publish the service in the form of an RMI protocol (or other service). The system can automatically generate an export proxy object for it without having to manually configure it. Generating Client Packages
When the MAVEN plug-in generates the client dependencies, the MAVEN plugin iterates through all the resources in the server's package, and when it discovers the identity of the @service on an interface, the plugin extracts the class file of the interface. It also analyzes the Pojo objects that the service relies on, and if the Pojo resource file exists in this server package, it will also be extracted to repackage the extracted resource files in a new client jar package. For invocation by the client caller. 3.7. Clients use distributed Services 3.7.1. Configuring the Client Package dependencies
In a customer development project, you need to add a server-side client jar in Maven's Pom.xml file, which contains only the Services service interface, and the Pojo object that the interface relies on. The configuration is as follows:
<dependencies> <dependency> <groupId>com.koubei</groupId> <artifactid>koubei-dian </artifactId> <version>1.4.1</version> < classifier>client</classifier > </ Dependency> </dependencies>
Note that the above dependency node requires the amount plus a classifier attribute, and the value must be client so that the project will be taken from the MAVEN library to the client package of the service pack at compile time. 3.7.2. Write Action
In WebWork, if you need to call a service object in a distributed service, it's easy to just change as follows:
public class Homeaction extends Actionsupport {private Ifreedianservice freedianservice; @Inject public void Setfreedians Ervice (Ifreedianservice freedianservice) {this.freedianservice = Freedianservice;} 3.7.3. Add Interceptor Configuration
In order for WebWork to recognize this @inject tag, you need to add an interceptor to the webwork.
<xwork> <interceptors> <interceptor name= "Distributeserviceinject" class= " Com.koubei.lina.ext.xwork.DistributeServiceInjectInterceptor "> </interceptor> </xwork>
The Distributeserviceinject interceptor needs to be added to the homeaction's default interceptor stack in order for Distributeserviceinject to function when the action is invoked. 3.8.Maven Plugin Introduction 3.8.1.ServiceClassManager
The role of the Com.koubei.plugin.distribute.ServiceGatewayBuild plug-in is to automatically generate Lina service agent files in the Classoutput folder during the compile phase of MAVEN. The contents of the document are as follows:
<?xml version= "1.0" encoding= "UTF-8"?> <! DOCTYPE beans Public "-//spring//dtd bean//en" "/spring-beans.dtd" > <beans> <import resource= "classpath: Dian.application.xml "/> <bean id= servicedelegate" class= "Com.koubei.lina.ext.DefaultServiceDelegate" > <property name= "Servicecenter" ref= "Servicecenter"/> <property name= "Port" ><value>9999</value ></property> <property name= "ServiceName" ><value>koubei-dian</value></property> </bean> <!-Service Center bean--> <bean id= "Servicecenter" class= " Com.koubei.lina.ext.svzcenter.ServiceCenterImpl "> <property name=" Moduledao "> <bean class=" Com.koubei.lina.ext.svzcenter.dao.LookupDao "/> </property> <property name=" Servicedao "> <bean class= "Com.koubei.lina.ext.svzcenter.dao.ServiceDao"/> </property> </bean> <bean class= " Org.springframework.remoting.rmi.RmiServiceExporter "> <property name=" service "ref=" ServicedelEgate "/> <property name=" ServiceName "> <value>koubei-dian_service</value> </property> <property name= "Serviceinterface" > <value>com.koubei.lina.ext.ServiceDelegate</value> </ property> <property name= "Registryport" > <value>9999</value> </property> </bean> </beans>
The port number in the above configuration file and the original target profile need to be configured in the configuration node of the Pom.xml plugin:
<plugin> <groupId>com.koubei</groupId> <artifactId>distribute-build</artifactId> <version>1.0-SNAPSHOT</version> <configuration> <springconfig>dian.application.xml</ springconfig> <port>9999</port> </configuration> </plugin> 3.8.2. Packageclientjarplugin
Package the client-dependent class files that are generated by the Servicegatewaybuild plug-in into a Clientjar package. 3.8.3. Servicegatewaybuild
Automatically extracts the class files that the server-side client relies on. 3.8.4. Custom plugin binding 3.8.5 with the MAVEN lifecycle . Publishing Services
Take the word of Mouth Shop Subcontract Project (Http://10.5.58.201/svn/Koubei/branches/Branch_galaxy_091014/koubei-dian) For example, Configure the custom plugin in the Pom.xml file of the project project:
<plugin> <groupId>com.koubei</groupId> <artifactId>distribute-build</artifactId> <version>1.0-SNAPSHOT</version> <configuration> <springconfig>dian.application.xml</ springconfig> <port>9999</port> </configuration> <executions> <execution> <id >compile</id> <phase>compile</phase> <goals> <goal>build</goal> </goals > </execution> <execution> <id>package</id> <phase>package</phase> <goals > <goal>distill</goal> <goal>clientjar</goal> </goals> </execution> </ Executions> </plugin>
Bind the three plug-ins mentioned above to the life cycle of maven execution.
All of these are configured to execute the MAVEN command under the Koubei-dian project:
Perform MVN package
Command will generate two jar packages under the project target directory. A Koubei-dian server-side jar package file (Koubei-dian-1.0.0.jar), and a client-dependent jar package file (Koubei-dian-1.0.0-client.jar).
Perform mvn deploy
The resulting two jar packs are automatically deployed to MAVEN's local repository. It can be found that if the plug-in is set up for the Koubei-dian project, the work of generating the jar will come down to the implementation of the MVN command, how simple it is. Here we have to marvel that Maven's functionality is too powerful, it has modeled all aspects of the lifecycle of the project's release, and allows users to customize the tasks that each lifecycle performs. This creates a beautiful and convenient build for the project release. 3.8.6. Start service
On the command line, execute the following command: Java-dservicemodule=koubei-dian ^
-classpath./target/koubei-dian-1.0.0.jar;^
d:/j2ee_solution/eclipse/workspace/lina/dist/lina.server.jar;^
d:/j2ee_solution/eclipse/workspace/lina/target/memcached-2.0.1.jar;^
d:/mvn_test/lina-ext/target/lina-ext-1.0-snapshot.jar;^
d:/j2ee_solution/eclipse/workspace/koubei-dian_bak/jars/log4j-1.2.12.jar;^
d:/j2ee_solution/eclipse/workspace/koubei-dian_bak/jars/commons-logging-1.0.4.jar;^
d:/j2ee_solution/wokspace/release20080225/webcontent/web-inf/lib/spring.jar;^
d:/j2ee_solution/eclipse/workspace/koubei-dian_bak/jars/commons-dbcp.jar;^
d:/j2ee_solution/eclipse/workspace/koubei-dian_bak/jars/commons-collections.jar;^
d:/j2ee_solution/eclipse/workspace/koubei-dian_bak/jars/commons-pool.jar;^
d:/j2ee_solution/wokspace/release20080225/dist/koubei-core.jar;^
d:/j2ee_solution/wokspace/release20080225/webcontent/web-inf/lib/taobao-cache.jar;^
d:/j2ee_solution/wokspace/release20080225/dist/koubei-util.jar;^
d:/j2ee_solution/wokspace/release20080225/webcontent/web-inf/lib/ibatis-2.3.0.677.jar;^
d:/j2ee_solution/wokspace/release20080225/dist/koubei-cache.jar;^
d:/j2ee_solution/wokspace/release20080225/webcontent/web-inf/lib/oscache-2.3.2.jar;^
d:/j2ee_solution/eclipse/workspace/koubei-dian_bak/jars/commons-beanutils.jar;^
d:/j2ee_solution/wokspace/release20080225/webcontent/web-inf/lib/commons-lang.jar;^
./config;^
D:/j2ee_solution/wokspace/release20080225/webcontent/web-inf/lib/mysql-connector-java-5.1.5-bin.jar ^
Com.koubei.lina.ext.ModuleLauncher
The service starts after the command is executed. 3.8.7. Service Monitoring Page
When the service server starts and registers the service information with the metadata server, it can publish the service externally. You can then open a local Web page to view the service objects on the local area network to verify that the required service objects exist. For example, to open a page: http://localhost/monitor/can see information about all the service objects in this local area network:
From this console you can view the following information: The name of the server name service that contains the service module, which is used to initialize the IP address of the port service where the service is initialized as the initialization parameter when spring starts
Service publication timestamp, which is used when verifying that the client code version is consistent with the server-side version, and when the server-side timestamp is compared to the client timestamp, the equivalent is consistent. 4. Things to be perfected 4.1. Using OSGi to transform existing service architectures
In the 3.8.6 boot service, you can see that the command to start the service is quite long, you can find that in the service startup command, Classpath In addition to koubei-dian-1.0.0.jar this jar package is a system-wide, other than the jar package, if you start multiple services, it is inevitable in the virtual System-level jar packs are repeatedly loaded in the machine, which is a waste of memory on the server.
In addition, some common beans that the service relies on, such as the DataSource object, can be shared for multiple services, and if you can save only one copy of the Dadasource object on the server, save the server memory for taking the object, It's good to update the DataSource configuration later.
These issues can be addressed using OSGi (public service gateways). In the following document, we will describe how to use OSGi to optimize the construction of an existing system. 4.2. Message Center
In the existing system, the information that synchronizes each service reference end object is synchronized with the Jgroup component, although I can test the performance in the native test environment, but has not been tested by the system-level large concurrency. I heard that the old comrade is developing asynchronous message system, it is said that the message system will be a highly reliable system, I think the time may be able to use this asynchronous messaging system to replace the existing Jgroup state synchronization problems. 4.3. Service Center Monitoring
Now in the monitoring center can only see what services may be invoked, the later transformation can be in the monitoring center can increase the workload of the monitoring and so on. 5. References Maven class loading mechanism http://maven.apache.org/guides/mini/guide-maven-classloading.html maven Plugin development approach http:// maven.apache.org/plugin-developers/index.html jgroups Introduction Http://www.jgroups.org/java annotations description http:// java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html Word-of-mouth Lina Description document Http://wiki.koubei.com/index.php/Rd/ Huoniao/lina