专业的编程技术博客社区

网站首页 > 博客文章 正文

netty+springboot打造高性能TCP+JSON/XML接口

baijin 2024-08-16 11:44:04 博客文章 10 ℃ 0 评论

介绍

netty+springboot打造高性能TCP+JSON/XML接口 使用tcp协议接口大大的提升了接口性能

软件架构

软件架构说明 SpringBoot2.1.5 + Netty 4.1.37

安装教程

下载源码

  1. 启动NettyApp
  2. 使用Jemter或其他TCP工具发送JSON/XML流式数据访问接口

使用说明

  1. Netty配置几乎都在yml/properties中可灵活配置,详见配置文件说明

下有

2、 主要类说明

Netty服务启动类:cn.com.bsfit.netty.server.NettySocketServer

数据接收处理器:cn.com.bsfit.netty.handler.SocketReceiveDataHandler,支持默认可接受最大数据1M,可自行配置

业务逻辑处理器:cn.com.bsfit.netty.handler.SocketRequestHandler,其父类使用模板方法完成固定流程,让业务处理类专注于业务

数据返回处理器:cn.com.bsfit.netty.handler.SocketResponseHandler

请求数据转化为通用格式Map处理类:cn.com.bsfit.netty.req.ReqData2MapFacade

可配置化文件类:cn.com.bsfit.netty.config.properties.BaseNettyServerProperties


3、如需了解更多,请查看源码以及doc文件夹下详细文档<<项目介绍.doc>>

4、使用说明

1、依赖引入

<dependencies>
    <!--依赖hdl-netty-->
    <dependency>
        <groupId>com.hdl</groupId>
        <artifactId>hdl-netty</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

2、业务接口实现并声明为Bean

/**
 * 类名 DemoService
 * 描述 样例,实现接口BusinessService,返回业务逻辑返回的数据
 * 默认是返回在body对象中
 * 返回格式 { "message": {"head": {}, "body": {}} }
 * 该这个标签格式可自定义实现
 *
 * @author hedonglin
 * @version 1.0
 * @date 2020/4/27 9:48
 */
@Service
public class DemoService implements BusinessService {
    @Override
    public Map<String, Object> reqHandler(Map<String, Object> reqMap, ReqData2MapFacade reqData2MapFacade) throws Exception {
        Map<String, Object> data = Maps.newHashMap();
        data.put("name", "hedonglin");

        // 获取facade中的数据
        boolean b = reqData2MapFacade.isJson();
        data.put("isJson", b);
        return BaseResponse.builder().success(data);
    }

    /**
     * 自定义异常返回结果(可重写,不重写返回默认错误数据结构BaseResponse#error方法)
     * @param errMsg 错误信息
     * @return 统一异常返回结果
     */
    @Override
    public Map<String, Object> getBaseResponseError(String errMsg) {
        Map<String, Object> result = Maps.newHashMap();
        result.put("code", "500");
        result.put("errMsg", errMsg);
        return result;
    }
}

3、配置文件

#######################################
# Netty Server Config
#######################################
netty:
  server:
    # netty功能启动开关, 默认为false
    enable: true
    # netty 主线程池(接受数据的线程池)大小,默认值为1
    bosses: 4
    # netty 工作线程池大小,默认值为1
    workers: 4
    # 数据格式转换线程池大小,默认转换JSON和XML两种格式,大小为2
    data-trans-poll-size: 2
    # 启动端口
    port: 8010
    # 启动延时,默认1000ms
    start-delay-time: 1000
    # 接受数据的缓冲区大小配置,单位是字节
    recbuf:
      # 最小值默认1KB
      min-size: 1024
      # 初始值默认为10K
      initial: 10240
      # 最大值默认为1M
      max-size: 1048576
    json-response:
      # JSON返回是否包含顶层字段(如果有顶层字段该配置才生效),默认是false
      contains-top: false
      # JSON返回是否包含Head字段(如果有Head字段该配置才生效),默认是true
      contains-head: false
      # JSON返回是否包含Body字段(如果有Body字段该配置才生效),默认是true
      contains-body: false
    xml-response:
      # Xml返回是否包含顶层字段(XML有顶层标签,所以这里只能设置为true),默认是true
      contains-top: true
    # 限制支持的顶层字段
    top-fields: Message,message
    # 限制支持的首部字段,与主体部分一段一一对应,默认支持配置Head
    head-fields: Head,head,HEAD
    # 限制支持的主体字段,与首部部分一段一一对应,默认支持配置Body
    body-fields: Body,body,BODY


4、入口程序类编写

package com.hdl.demo;

/**
 * 类名 DemoApplication
 * 描述 TODO
 *
 * @author hedonglin
 * @version 1.0
 * @date 2020/4/27 9:54
 */

import cn.com.bsfit.netty.NettyApp;
import cn.com.bsfit.netty.config.base.BaseConfigurable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;

/**
 * 类名 NettyApp
 * 描述 主程序启动类
 *
 * @author hedonglin
 * @version 1.0
 * @date 2019/9/29 9:43
 */
@Slf4j
@EnableAutoConfiguration
@ComponentScan(basePackages = {"cn.*", "com.*", "net.*"},
        // 不适用默认的过滤器
        useDefaultFilters = false,
        //includeFilters 只扫描指定的类
        includeFilters = {
                // 只有实现了BaseConfigurable接口的类才回被扫描
                @ComponentScan.Filter(value = {BaseConfigurable.class},
                        // 过滤类型为指定的类型,比如某个类
                        type = FilterType.ASSIGNABLE_TYPE)}
         ,
        // 不扫描NettyApp.class(重要)
        excludeFilters = {
                @ComponentScan.Filter(classes = NettyApp.class)
        }
)
public class DemoApplication {
    public static void main(String[] args) {
        try {
            SpringApplication app = new SpringApplicationBuilder().bannerMode(Banner.Mode.OFF).sources(NettyApp.class).build();
            app.run(args);
        } catch (Exception e) {
            log.error("请确认已正确配置该应用,请检查是否正确配置");
        }
    }
}

5、启动DemoApplication

12:36:12.691 [main] INFO  com.hdl.demo.DemoApplication - No active profile set, falling back to default profiles: default
12:36:16.537 [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat initialized with port(s): 8080 (http)
12:36:16.559 [main] INFO  o.a.coyote.http11.Http11NioProtocol - Initializing ProtocolHandler ["http-nio-8080"]
12:36:16.575 [main] INFO  o.a.catalina.core.StandardService - Starting service [Tomcat]
12:36:16.576 [main] INFO  o.a.catalina.core.StandardEngine - Starting Servlet engine: [Apache Tomcat/9.0.19]
12:36:16.754 [main] INFO  o.a.c.c.C.[Tomcat].[localhost].[/] - Initializing Spring embedded WebApplicationContext
12:36:16.754 [main] INFO  o.s.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 3971 ms
12:36:16.997 [main] INFO  c.c.bsfit.netty.utils.SpringBeanUtil - ---------------------------------------------------------------------
12:36:16.997 [main] INFO  c.c.bsfit.netty.utils.SpringBeanUtil - ========ApplicationContext配置成功========
12:36:16.997 [main] INFO  c.c.bsfit.netty.utils.SpringBeanUtil - ---------------------------------------------------------------------
12:36:17.443 [main] INFO  c.c.b.netty.server.NettySocketServer - netty application starting
12:36:17.446 [main] INFO  o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8080"]
12:36:17.469 [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8080 (http) with context path ''
12:36:17.474 [main] INFO  com.hdl.demo.DemoApplication - Started DemoApplication in 5.645 seconds (JVM running for 7.472)
**12:36:18.941 [netty主线程-0] INFO  c.c.b.netty.server.NettySocketServer - Socket server bound successfully,the port is 8010**

6、重要配置详解

    json-response:
      # JSON返回是否包含顶层字段(如果有顶层字段该配置才生效),默认是false
      contains-top: false
      # JSON返回是否包含Head字段(如果有Head字段该配置才生效),默认是true
      contains-head: false
      # JSON返回是否包含Body字段(如果有Body字段该配置才生效),默认是true
      contains-body: false
    xml-response:
      # Xml返回是否包含顶层字段(XML有顶层标签,所以这里只能设置为true),默认是true
      contains-top: true
    # 限制支持的顶层字段
    top-fields: Message,message
    # 限制支持的首部字段,与主体部分一段一一对应,默认支持配置Head
    head-fields: Head,head,HEAD
    # 限制支持的主体字段,与首部部分一段一一对应,默认支持配置Body
    body-fields: Body,body,BODY

如果是JSON请求,且需要格式请求和响应格式,如

{ 
  "Message": {
    "Head": {
        "headKey": "测试头"
    }, 
    "Body": {
        "bodyKey": "测试体"
    }
  }
}

Message, Head, Body 都可以后台配置,并且可以使用开关关闭。

使用jmeter发送TCP请求 注意:

1、jmeter默认TCP的编码格式不是UTF-8, 需要在bin/jmeter.properties中修改tcp编码。
    2、jmeter发送tcp请求时,需要关闭连接(选中close connection),因为实现的时短连接。
    3、如果时XML请求,则必须存在顶层标签


原文地址:https://gitee.com/hdl_1107/hdl-parent/tree/master

作者:hedonglin

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表