com.msa.rpc.server.RpcServer Maven / Gradle / Ivy
Show all versions of msa-rpc-server Show documentation
package com.msa.rpc.server;
import com.google.common.collect.Maps;
import com.msa.api.regcovery.registry.ServiceRegistry;
import com.msa.rpc.common.bean.RpcRequest;
import com.msa.rpc.common.bean.RpcResponse;
import com.msa.rpc.common.codec.RpcDecoder;
import com.msa.rpc.common.codec.RpcEncoder;
import com.msa.rpc.server.annotation.RpcService;
import com.msa.rpc.server.handler.RpcServerReqHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
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 lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import java.net.InetAddress;
import java.util.Map;
/**
* The type Rpc server.
*/
@Slf4j
@Data
public class RpcServer implements ApplicationContextAware, InitializingBean {
/**
* The Port.
*/
private int port;
/**
* The Handler map.
*/
private final Map handlerMap = Maps.newHashMap();
/**
* The Registry.
*/
private ServiceRegistry registry;
/**
* 服务扫描
* Sets application context.
*
* @param applicationContext the application context
* @throws BeansException the beans exception
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map serviceBeanMap = applicationContext.getBeansWithAnnotation(RpcService.class);
if (CollectionUtils.isEmpty(serviceBeanMap)) {
log.warn(">>>>>>>>>>>===warn:no service beans for rpc4j");
return;
}
serviceBeanMap.forEach((beanName, serviceBean) -> {
RpcService rpcService = serviceBean.getClass().getAnnotation(RpcService.class);
String serviceName = rpcService.value().getName();
try {
Class clazz = ClassUtils.getDefaultClassLoader().loadClass(serviceName);
if (!clazz.isInterface()) {
throw new IllegalArgumentException(serviceName + " must be a interface");
}
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException(serviceName + " in classpath not find");
}
handlerMap.put(serviceName, serviceBean);
});
}
/**
* After properties set.
*
* @throws Exception the exception
*/
@Override
public void afterPropertiesSet() throws Exception {
// 注册RPC服务地址
String serviceAddr = InetAddress.getLocalHost().getHostAddress() + ":" + port;
handlerMap.forEach((serviceName, instance) -> {
registry.registry(serviceName, serviceAddr);
log.debug(">>>>>>>>>>===registry service: {} ==> {}", serviceName, serviceAddr);
});
//异步启动netty
Thread thread = new Thread(new RpcServerRunable(port, handlerMap));
thread.setDaemon(true);
thread.start();
}
/**
* The type Rpc server runable.
*/
public static class RpcServerRunable implements Runnable {
/**
* The Port.
*/
private int port;
/**
* The Handler map.
*/
private Map handlerMap;
/**
* Instantiates a new Rpc server runable.
*
* @param port the port
* @param handlerMap the handler map
*/
public RpcServerRunable(int port, Map handlerMap) {
this.port = port;
this.handlerMap = handlerMap;
}
/**
* When an object implementing interface Runnable
is used
* to create a thread, starting the thread causes the object's
* run
method to be called in that separately executing
* thread.
*
* The general contract of the method run
is that it may
* take any action whatsoever.
*
* @see Thread#run() Thread#run()Thread#run()Thread#run()Thread#run()Thread#run()
*/
@Override
public void run() {
EventLoopGroup group = new NioEventLoopGroup();
EventLoopGroup childGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(group, childGroup);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
// 解码RPC请求
pipeline.addLast(new RpcDecoder(RpcRequest.class));
// 编码RPC响应
pipeline.addLast(new RpcEncoder(RpcResponse.class));
// 处理RPC请求
pipeline.addLast(new RpcServerReqHandler(handlerMap));
}
});
ChannelFuture future = bootstrap.bind(port).sync();
log.debug("server started, listening on {}", port);
// 释放资源
future.channel().closeFuture().sync();
} catch (Exception e) {
log.error(">>>>>>>>>===server start exception", e);
} finally {
// 关闭RPC服务
childGroup.shutdownGracefully();
group.shutdownGracefully();
}
}
}
}