The company’s latest project, the Lolttery, is already under construction.

Because micro service is very popular, before special research for a while. Decide on a microservice structure for the new project. Start documenting learning and development issues and progress in this blog.

Using Netty+Spring+ Mybatis core framework, internal communication using SOCKET TCP communication. The protocol is JSON. Also use Spring MVC as the external HTTP interface. The database uses Mysql+Redis.

Alas…… Anyway, the server + Web terminal is my own life, with what technology need not discuss ah……

Personal experience is not very rich, this series of blog as a learning log and tread pit notes, welcome all the gods pat brick correction.


The framework of netTY service framework is NetTY service. Netty is an excellent asynchronous network processing framework. Various Handles can adapt to different network protocols. At the same time, it is not dependent on middleware such as Tomcat, so it is a suitable choice to implement microservices.

Netty service basically copied the official website source code.

The initiator contains spring initialization, Netty startup, and service registration.

/** * Created by shizhida on 16/3/15. */ public class Bootstrap {private int port = 2333; public static String serverName =""; private Logger logger = LoggerFactory.getLogger(Bootstrap.class); Public Bootstrap(int port){// Get the spring context when initializing the initiator. ApplicationContext context = new AnnotationConfigApplicationContext(Application.class); / / to add context to a global variable is easy to use Application. SetApplicationContext (context); this.port = port; } /** * Register this service in Redis so that clients can get * @param host * @param serverName * @return
     */
    public Bootstrap register(String host,String serverName){
        RedisDao redisDao = new RedisDao("localhost");
        Map<String,String> info = new HashMap<>();
        info.put("ip",host);
        info.put("port",port+"");
        this.serverName = serverName;
        redisDao.getJedis().hmset(serverName,info);
        returnthis; } /** * netty starts * @throws Exception */ public void run() throws Exception {EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast( new JsonDecoder(), new DispatchHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE,true); ChannelFuture f = b.bind(port).sync(); // Save to a global variable to close the service application.future = f; logger.info("start service bin port " + port);

            f.channel().closeFuture().sync();

        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        try {
            new Bootstrap(2333).register("locahost"."server").run(); } catch (Exception e) { e.printStackTrace(); }}}Copy the code

After the initiator is complete, the protocol is resolved

To avoid sticky packets or half-packets, the protocol uses a 4byte packet length +json string for transmission.

Json consists of header, body, and foot. Header contains the request information such as serviceName and serviceCode. Body is the request parameter, and Foot contains the source and verification code

Self-written parser as follows, JSON parsing using Ali’s FastJSON library

	
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {// If the readable length is less than 4 bytes, the data is not readif(in.readableBytes()<4)
        {
            logger.debug("Insufficient length, readable length:" + in.readableBytes());
            return; } byte[] byte_length = new byte[4]; in.readBytes(byte_length); Int length = butil. bytes2int(byte_length,0); // If the readable length is smaller than the specified length, no reading is performedif(in.readableBytes()<length)
        {
            logger.debug("The readable length is less than the convention length, convention:"+length+"Readable"+in.readableBytes());
            in.resetReaderIndex();
            return;
        }
        logger.debug("Convention read data length:" + length);
        byte[] data = new byte[length];
 
        in.readBytes(data);
 
        String json  = new String(data);
        logger.debug("Read character data:"+new String(data)); JSONObject object = JSON.parseObject(json); Request = new XORequest(object); out.add(request); }Copy the code

Then there is the distribution of services.

A service can also be subdivided into multiple businesses. The serviceName and serviceCode are designed to identify a specific business. ServiceName Is used to register the service and obtain the IP address and port information of the service. ServiceCode is used to divide services within a service.

Using the spring framework’s capabilities, service distribution can be done simply: Netty handles:

Public void channelRead(ChannelHandlerContext CTX, Object MSG) {XORequest request = (XORequest) MSG; logger.info("-------------request start ------------");
        logger.info("request to "+request.getServiceName());
        logger.info("request at "+new Date(request.getRequestDate()));
        logger.info("request for "+request.getServiceCode()); XOResponse result = dispatcher.dispatch(request); Byte [] json = result.toString().getbytes (); byte[] json = result.tostring ().getbytes (); ByteBuf byteBuf = ctx.alloc().buffer(json.length); byteBuf.writeBytes(json); // Send final ChannelFuture f = ctx.writeAndFlush(byteBuf); f.addListener(newChannelFutureListener() {
                        public void operationComplete(ChannelFuture future) {
                assert f == future;
                ctx.close();
                logger.info("request process done"); }}); }Copy the code

Distribution services :(dispatcher)

public XOResponse dispatch(XORequest request) { String service_code = request.getServiceCode(); XOService service = Application.applicationContext.getBean(service_code,XOService.class); return service.run(request); }

By default all services implement XOService interface, utilizing Spring's Service("serviceCode"Annotations can easily implement service distribution. Through two-tier dispensers, common protocols, and service interfaces. This is where a high degree of separation of business logic and framework functionality is achieved. Implementing the business logic simply requires adding more instances of XOService interfaces to extend the business logic. Relying on the framework on each Service, implementing a Bootstrap launcher and adding business logic code such as Service can complete a new Service.Copy the code