网络编程 -- RPC实现原理 -- 目录

  啦啦啦

V4——RPC -- 远程方法调用 + Spring 自动注册

  服务提供商:

    1. 配置 rpc04_server.xml 注入 服务提供商 rpcServiceProvider并指定初始化方法、销毁方法 及 服务实例 IUserService

    2. 读取 服务消费者 请求的 MethodStaics ,通过反射获取服务端实例方法的返回值。返回值为null值,则映射为NullWritable实例返回。不为null,则不加以约束。

  服务消费者:

    1. 配置 rpc04_client.xml 注入 服务注册类 ProxyBeanRegistry 并指定 服务提供商地址 及 注册服务 。

    2. 服务注册类 实现 BeanFactoryPostProcessor 接口,容器启动后 注入 RemoteRPCClient 实例 及 注册服务代理对象

服务提供商:

  XML : rpc04_server.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
classpath:/org/springframework/beans/factory/xml/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
classpath:/org/springframework/context/config/spring-context-4.1.xsd
http://mybatis.org/schema/mybatis-spring
http://mybatis.org/schema/mybatis-spring.xsd
http://www.springframework.org/schema/aop
classpath:org/springframework/aop/config/spring-aop-4.1.xsd"
default-lazy-init="false"> <bean id="rpcServiceProvider" class="lime.pri.limeNio.netty.rpc04.core.server.RPCServiceProvider" >
<constructor-arg index="0" value="9999"/>
</bean> <bean id="IUserService" class="lime.pri.limeNio.netty.rpc04.service.impl.UserService"/> </beans>

  Class : RPCServiceProvider

package lime.pri.limeNio.netty.rpc04.core.server;

import java.lang.reflect.Method;
import java.util.List; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.CharsetUtil;
import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;
import lime.pri.limeNio.netty.rpc04.core.assist.NullWritable; public class RPCServiceProvider implements ApplicationContextAware, InitializingBean, DisposableBean { private ServerBootstrap serverBootstrap;
private EventLoopGroup boss;
private EventLoopGroup worker;
private int port; private ApplicationContext act; public RPCServiceProvider() {
super();
} public RPCServiceProvider(int port) {
this.serverBootstrap = new ServerBootstrap();
this.boss = new NioEventLoopGroup();
this.worker = new NioEventLoopGroup();
this.serverBootstrap.group(boss, worker);
this.serverBootstrap.channel(NioServerSocketChannel.class);
this.port = port;
} public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.act = applicationContext;
} public void afterPropertiesSet() throws Exception {
serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LengthFieldPrepender(2))
.addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2))
.addLast(new MessageToMessageCodec<ByteBuf, Object>() {
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out)
throws Exception {
out.add(Unpooled.buffer()
.writeBytes(JSON.toJSONString(msg, SerializerFeature.WriteClassName)
.getBytes(CharsetUtil.UTF_8)));
} @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)
throws Exception {
out.add(JSON.parse(msg.toString(CharsetUtil.UTF_8)));
}
}).addLast(new ChannelHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
MethodStaics methodStaics = (MethodStaics) msg;
Object invoke = null;
try {
Object bean = act.getBean(methodStaics.getTargetInterface());
Method method = bean.getClass().getDeclaredMethod(methodStaics.getMethod(),
methodStaics.getParameterTypes());
invoke = method.invoke(bean, methodStaics.getArgs());
                      if(null == invoke)
                        throw new NullPointException();
} catch (NullPointerException e) {
//如果返回值为空,则返回NullWritable实例代替传输
                      invoke = new NullWritable();
}
ChannelFuture channelFuture = ctx.writeAndFlush(invoke);
channelFuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
channelFuture.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
channelFuture.addListener(ChannelFutureListener.CLOSE);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println(cause);
}
});
}
});
/**
* 绑定监听端口并启动服务 注意 : 启动的服务是阻塞的,防止阻塞Spring工厂采用异步启动
*/
new Thread() {
public void run() {
try {
System.out.println("服务启动@" + port + " ...");
ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
System.out.println(e);
} finally {
} };
}.start();
} public void destroy() throws Exception {
boss.shutdownGracefully();
worker.shutdownGracefully();
}
}

  Class : IUserService

package lime.pri.limeNio.netty.rpc04.service;

import java.util.List;

import lime.pri.limeNio.netty.rpc04.entity.User;

public interface IUserService {

    User queryById(Integer id);

    List<User> queryByName(String name);

    List<User> queryAll(Integer pageSize, Integer pageNum);
}

  Class : UserService

package lime.pri.limeNio.netty.rpc04.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import lime.pri.limeNio.netty.rpc04.entity.User;
import lime.pri.limeNio.netty.rpc04.service.IUserService; public class UserService implements IUserService { private static Map<Integer, User> userMap = new ConcurrentHashMap<Integer, User>(); static {
for (int i = 1; i <= 100; i++) {
userMap.put(i, new User(i, "lime_" + i, new Date()));
}
} public User queryById(Integer id) {
return userMap.get(id);
} public List<User> queryAll(Integer pageSize, Integer pageNum) {
int stNum = (pageNum - 1) * pageSize + 1;
int enNum = pageNum * pageSize;
List<User> result = new ArrayList<User>();
for (int i = stNum; i <= enNum; i++) {
result.add(userMap.get(i));
}
return result;
} public static void main(String[] args) {
UserService userService = new UserService();
for (User user : userService.queryAll(10, 2)) {
System.out.println(user);
}
System.out.println(userService.queryById(100));
} public List<User> queryByName(String name) {
List<User> result = null;
Iterator<User> iterator = userMap.values().iterator();
while (iterator.hasNext()) {
User user = iterator.next();
if (user.getName().equals(name)) {
if (null == result)
result = new ArrayList<User>();
result.add(user);
}
}
return result;
} }

服务消费者:

  XML : rpc04_client.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
classpath:/org/springframework/beans/factory/xml/spring-beans-4.1.xsd
http://www.springframework.org/schema/context
classpath:/org/springframework/context/config/spring-context-4.1.xsd
http://mybatis.org/schema/mybatis-spring
http://mybatis.org/schema/mybatis-spring.xsd
http://www.springframework.org/schema/aop
classpath:org/springframework/aop/config/spring-aop-4.1.xsd"
default-lazy-init="false"> <bean class="lime.pri.limeNio.netty.rpc04.core.registry.ProxyBeanRegistry">
<constructor-arg index="0">
<bean class="lime.pri.limeNio.netty.rpc04.core.client.assist.HostAndPort">
<constructor-arg index="0" value="127.0.0.1" />
<constructor-arg index="1" value="9999" />
</bean>
</constructor-arg>
<property name="proxyBeanMap">
<map>
<entry key="userService" value="lime.pri.limeNio.netty.rpc04.service.IUserService" />
<entry key="personService" value="lime.pri.limeNio.netty.rpc04.service.IUserService" />
</map>
</property>
</bean> </beans>

  Class : ProxyBeanRegistry

package lime.pri.limeNio.netty.rpc04.core.registry;

import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.util.CollectionUtils; import lime.pri.limeNio.netty.rpc04.core.client.assist.HostAndPort;
import lime.pri.limeNio.netty.rpc04.core.client.proxy.RPCObjectProxy;
import lime.pri.limeNio.netty.rpc04.core.client.rpcClient.impl.RemoteRPCClient; /**
* 通过postProcessBeanFactory()向beanFactory注册实体Bean
*
* @author lime
*
*/
public class ProxyBeanRegistry implements BeanFactoryPostProcessor { private Map<String, Class<?>> proxyBeanMap;
private HostAndPort hap; public ProxyBeanRegistry() {
super();
} public ProxyBeanRegistry(HostAndPort hap) {
super();
this.hap = hap;
} public void postProcessBeanFactory(ConfigurableListableBeanFactory listableBeanFactory) throws BeansException {
DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) listableBeanFactory;
// 配置RemoteRPCClient实例:HostAndPort
BeanDefinitionBuilder remoteRPCClient = BeanDefinitionBuilder.genericBeanDefinition(RemoteRPCClient.class);
remoteRPCClient.addConstructorArgValue(hap);
AbstractBeanDefinition remoteRPCClientBeanDefinition = remoteRPCClient.getBeanDefinition();
defaultListableBeanFactory.registerBeanDefinition("remoteRPCClient", remoteRPCClientBeanDefinition); // 配置RPCObjectProxy实例:注册的接口、服务消费者
if(!CollectionUtils.isEmpty(proxyBeanMap)){
for(Map.Entry<String, Class<?>> entry : proxyBeanMap.entrySet()){
String beanName = entry.getKey(); //注册Bean的名字
Class<?> beanClazz = entry.getValue(); //需要代理的接口
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(RPCObjectProxy.class);
beanDefinitionBuilder.addConstructorArgReference("remoteRPCClient");
beanDefinitionBuilder.addConstructorArgValue(beanClazz);
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
defaultListableBeanFactory.registerBeanDefinition(beanName, beanDefinition);
}
}
} public void setProxyBeanMap(Map<String, Class<?>> proxyBeanMap) {
this.proxyBeanMap = proxyBeanMap;
} }

 Class : RPCClient

package lime.pri.limeNio.netty.rpc04.core.client.rpcClient;

import org.springframework.beans.factory.DisposableBean;

import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;

/**
* 通过RPCClient实现对远程方法的调用
*
* @author lime
*
*/
public interface RPCClient extends DisposableBean { Object invokeMethod(MethodStaics methodStaics); }

  Class : RemoteRPCClient

package lime.pri.limeNio.netty.rpc04.core.client.rpcClient.impl;

import java.net.InetSocketAddress;
import java.util.List; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature; import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.MessageToMessageCodec;
import io.netty.util.CharsetUtil;
import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;
import lime.pri.limeNio.netty.rpc04.core.assist.NullWritable;
import lime.pri.limeNio.netty.rpc04.core.client.assist.HostAndPort;
import lime.pri.limeNio.netty.rpc04.core.client.rpcClient.RPCClient; /**
* 通过TCP/IP协议实现远程方法调用
*
* @author lime
*
*/
public class RemoteRPCClient implements RPCClient { private Bootstrap bootstrap;
private EventLoopGroup worker;
private HostAndPort hostAndPort; public RemoteRPCClient() {
super();
} public RemoteRPCClient(HostAndPort hostAndPost) {
this.hostAndPort = hostAndPost;
// 初始化数据
this.bootstrap = new Bootstrap();
this.worker = new NioEventLoopGroup();
this.bootstrap.group(this.worker);
this.bootstrap.channel(NioSocketChannel.class);
} public Object invokeMethod(final MethodStaics methodStaics) {
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2, 0, 2))
.addLast(new LengthFieldPrepender(2)).addLast(new MessageToMessageCodec<ByteBuf, Object>() {
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, List<Object> out)
throws Exception {
out.add(Unpooled.buffer()
.writeBytes(JSON.toJSONString(msg, SerializerFeature.WriteClassName)
.getBytes(CharsetUtil.UTF_8)));
} @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out)
throws Exception {
out.add(JSON.parse(msg.toString(CharsetUtil.UTF_8)));
}
}).addLast(new ChannelHandlerAdapter() {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ChannelFuture channelFuture = ctx.writeAndFlush(methodStaics);
channelFuture.addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
channelFuture.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
methodStaics.setResult(msg);
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.err.println(cause);
}
});
}
});
ChannelFuture channelFuture;
try {
channelFuture = bootstrap.connect(new InetSocketAddress(hostAndPort.getHost(), hostAndPort.getPort()))
.sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 服务端返回值为null,处理方式
return methodStaics.getResult() instanceof NullWritable ? null : methodStaics.getResult();
} public void destroy() throws Exception {
worker.shutdownGracefully();
}
}

  Class : RPCObjectProxy

package lime.pri.limeNio.netty.rpc04.core.client.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy; import org.springframework.beans.factory.FactoryBean; import lime.pri.limeNio.netty.rpc04.core.assist.MethodStaics;
import lime.pri.limeNio.netty.rpc04.core.client.rpcClient.RPCClient; /**
* 通过接口动态创建代理对象
*
* @author lime
* @param <T>
*
* 实现FactoryBean接口,与Spring整合
*
*/
public class RPCObjectProxy implements InvocationHandler, FactoryBean<Object> { private RPCClient rpcClient;
private Class<?> targetInterface; public RPCObjectProxy() {
super();
} public RPCObjectProxy(RPCClient rpcClient, Class<?> targetInterface) {
super();
this.rpcClient = rpcClient;
this.targetInterface = targetInterface;
} public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return rpcClient
.invokeMethod(new MethodStaics(targetInterface, method.getName(), args, method.getParameterTypes()));
} // 产生代理对象
public Object getObject() throws Exception {
return Proxy.newProxyInstance(RPCObjectProxy.class.getClassLoader(), new Class[] { targetInterface }, this); } public Class<?> getObjectType() {
return targetInterface;
} public boolean isSingleton() {
return true;
}
}

  Class : HostAndPort

package lime.pri.limeNio.netty.rpc04.core.client.assist;

import java.io.Serializable;

public class HostAndPort implements Serializable{

    /**
*
*/
private static final long serialVersionUID = 1L; private String host;
private int port;
public HostAndPort() {
super();
// TODO Auto-generated constructor stub
}
public HostAndPort(String host, int port) {
super();
this.host = host;
this.port = port;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
@Override
public String toString() {
return "HostAndPort [host=" + host + ", port=" + port + "]";
} }

辅助类 :

  Class : MethodStaics

package lime.pri.limeNio.netty.rpc04.core.assist;

import java.io.Serializable;
import java.util.Arrays; /**
* @author lime
*
*/
public class MethodStaics implements Serializable{ /**
*
*/
private static final long serialVersionUID = 1L;
private Class<?> targetInterface;
private String method;
private Object[] args;
private Class[] parameterTypes;
private Object result;
public MethodStaics() {
super();
// TODO Auto-generated constructor stub
}
public MethodStaics(Class<?> targetInterface, String method, Object[] args, Class[] parameterTypes) {
super();
this.targetInterface = targetInterface;
this.method = method;
this.args = args;
this.parameterTypes = parameterTypes;
}
@Override
public String toString() {
return "MethodStaics [targetInterface=" + targetInterface + ", method=" + method + ", args="
+ Arrays.toString(args) + ", parameterTypes=" + Arrays.toString(parameterTypes) + "]";
}
public Class<?> getTargetInterface() {
return targetInterface;
}
public void setTargetInterface(Class<?> targetInterface) {
this.targetInterface = targetInterface;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public Object[] getArgs() {
return args;
}
public void setArgs(Object[] args) {
this.args = args;
}
public Class[] getParameterTypes() {
return parameterTypes;
}
public void setParameterTypes(Class[] parameterTypes) {
this.parameterTypes = parameterTypes;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
} }

  Class : NullWritable

package lime.pri.limeNio.netty.rpc04.core.assist;

import java.io.Serializable;

public class NullWritable implements Serializable{

    /**
*
*/
private static final long serialVersionUID = 1L; }

  Class : User

package lime.pri.limeNio.netty.rpc04.entity;

import java.io.Serializable;
import java.util.Date; public class User implements Serializable{ /**
*
*/
private static final long serialVersionUID = 1L; private int id;
private String name;
private Date birth;
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(int id, String name, Date birth) {
super();
this.id = id;
this.name = name;
this.birth = birth;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", birth=" + birth + "]";
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
} }

测试类 :

  Class : TtServer

package lime.pri.limeNio.netty.rpc04.tT;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TtServer {

    public static void main(String[] args) throws Exception {
new ClassPathXmlApplicationContext("classpath:spring/rpc04_server.xml");
}
}

  Class :

package lime.pri.limeNio.netty.rpc04.tT;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; import lime.pri.limeNio.netty.rpc04.entity.User;
import lime.pri.limeNio.netty.rpc04.service.IUserService; public class TtClient { public static void main(String[] args) throws Exception {
ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:spring/rpc04_client.xml");
IUserService userService = (IUserService) ctx.getBean("userService");
User user = userService.queryById(23);
System.out.println(user);
System.out.println("-- --");
IUserService personService = (IUserService) ctx.getBean("personService");
List<User> list = personService.queryAll(10, 4);
for(User u : list){
System.out.println(u);
}
}
}

  Console : Server

六月 25, 2017 3:35:47 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17f052a3: startup date [Sun Jun 25 15:35:47 CST 2017]; root of context hierarchy
六月 25, 2017 3:35:47 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring/rpc04_server.xml]
服务启动@9999 ...

  Console : Client

六月 25, 2017 3:52:39 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17f052a3: startup date [Sun Jun 25 15:52:39 CST 2017]; root of context hierarchy
六月 25, 2017 3:52:39 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [spring/rpc04_client.xml]
User [id=23, name=lime_23, birth=Sun Jun 25 15:52:10 CST 2017]
-- --
User [id=31, name=lime_31, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=32, name=lime_32, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=33, name=lime_33, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=34, name=lime_34, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=35, name=lime_35, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=36, name=lime_36, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=37, name=lime_37, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=38, name=lime_38, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=39, name=lime_39, birth=Sun Jun 25 15:52:10 CST 2017]
User [id=40, name=lime_40, birth=Sun Jun 25 15:52:10 CST 2017]
-- --
null
-- --

啦啦啦

网络编程 -- RPC实现原理 -- RPC -- 迭代版本V4 -- 远程方法调用 整合 Spring 自动注册的更多相关文章

  1. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V4 -- 粘包拆包

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- new LengthFieldPrepender(2) : 设置数据包 2 字节的特征码 new LengthFieldB ...

  2. 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V3 -- 远程方法调用 整合 Spring

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V3——RPC -- 远程方法调用 及 null的传输 + Spring 服务提供商: 1. 配置 rpc03_server.xml 注入 服务提供 ...

  3. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V1 -- 入门应用

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V1——Netty入门应用 Class : NIOServerBootStrap package lime.pri.limeNio.netty.ne ...

  4. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V2 -- 对象传输

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- 使用序列化和反序列化在网络上传输对象:需要实现 java.io.Serializable 接口 只能传输( ByteBuf ...

  5. 网络编程 -- RPC实现原理 -- Netty -- 迭代版本V3 -- 编码解码

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——Netty -- pipeline.addLast(io.netty.handler.codec.MessageToMessageCodec ...

  6. 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V1 -- 本地方法调用

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V1——RPC -- 本地方法调用:不通过网络 入门 1. RPCObjectProxy rpcObjectProxy = new RPCObjec ...

  7. 网络编程 -- RPC实现原理 -- RPC -- 迭代版本V2 -- 本地方法调用 整合 Spring

    网络编程 -- RPC实现原理 -- 目录 啦啦啦 V2——RPC -- 本地方法调用 + Spring 1. 配置applicationContext.xml文件 注入 bean 及 管理 bean ...

  8. Java网络编程UDP通信原理

    前言 继续今天我们的Java网络编程--TCP和UDP通信 一.TCP和UDP概述 传输层通常以TCP和UDP协议来控制端点与端点的通信   TCP UDP 协议名称 传输控制协议 用户数据包协议 是 ...

  9. UNIX网络编程——Socket通信原理和实践

    我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览器浏览网页时,浏览器的进程怎么与web服务器通信的?当你用QQ聊天时,QQ进程怎么与服务器或你好友所在的QQ进程通信?这些都得靠so ...

随机推荐

  1. css 类选择器结合元素选择器和多类选择器

    1.结合元素选择器 <p class="important">css</p> p.important {color: red} 匹配class属性包含imp ...

  2. 在Windows环境下使用docker

    Widows下的Docker工具有两个:Docker Toolbox,和Docker Desktop,其中后者是在win10下才能使用的,提供了更强大的功能.由于我个人的电脑是win7环境,用的就是d ...

  3. 【T08】避免重新编写TCP

    1.有时候为了所谓的性能,我们倾向于使用udp,但是我们又期望数据的传输是可靠的,因此需要在应用层提供可靠性. 2.可靠.健壮的udp必须提供: a.在合理的时间内没有收到回复,进行重传 b.保证应答 ...

  4. Android添加全屏启动画面

    有的Android软件需要在启动的时候显示一个启动画面,可以是一张图或者一些设置什么呢,还有一个好处就是,可以趁机在后台加载数据.创建启动画面一般有两种方式:1.建立一个activity,展示启动画面 ...

  5. 微软BI 之SSIS 系列 - 在 SSIS 中使用 Web Service 以及 XML 解析

    开篇介绍 Web Service 的用途非常广几乎无处不在,像各大门户网站上的天气预报使用到的第三方 Web Service API,像手机客户端和服务器端的交互等都可以通过事先设计好的 Web Se ...

  6. linux 使用ifstat查看网络使用情况

    首先安装ifstat wget http://distfiles.macports.org/ifstat/ifstat-1.1.tar.gz tar xzvf ifstat-1.1.tar.gz cd ...

  7. 救基友3(三维BFS)

    救基友记3 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描写叙述   话说CZ因为不守基道.被妖怪抓走了.好基友WP在努力讨好高富帅 ...

  8. top命令详析及排查问题使用演示

    1. top基本使用 top命令运行图 第一行:基本信息 第二行:任务信息 第三行:CPU使用情况 第四行:物理内存使用情况 buff/cache: buffers 和 cache 都是内存中存放的数 ...

  9. 第三部分:Android 应用程序接口指南---第二节:UI---第五章 设置(Settings)

    第5章 设置(Settings) 应用程序通常包括允许用户修改应用程序的特性和行为的设置功能.例如,一些应用程序允许用户指定通知是否启用或指定多久使用云同步数据.如果你想要为你的应用程序提供设置,你应 ...

  10. linux每日命令(9):cp命令

    一.命令格式: cp [参数] source dest 或 cp [参数] source... directory 二.命令功能: 将源文件复制至目标文件,或将多个源文件复制至目标目录. 三. 命令参 ...