How to Build Robust, High‑Concurrency APIs: Design, Security, and Scaling Tips

This article outlines practical guidelines for designing and implementing enterprise‑grade APIs, covering request/response definitions, unified error handling, interceptor chains, token‑based authentication, rate limiting, load balancing, clustering, caching, and strategies for achieving high concurrency and high availability.

Code Ape Tech Column
Code Ape Tech Column
Code Ape Tech Column
How to Build Robust, High‑Concurrency APIs: Design, Security, and Scaling Tips

What Is an API?

An API is a server endpoint that receives client requests with a predefined set of parameters, processes the request, and returns data in a specified format such as JSON or XML.

Key Development Considerations

1. Define Input Parameters

Write a clear API contract that documents each request parameter, its type, whether it is required, and any validation rules.

2. Define Output Structure

Encapsulate responses in a consistent wrapper that includes a result code, message, and payload. Example response models:

package com.caiex.vb.model;

import java.io.Serializable;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Result", propOrder = {"resultCode", "resultMsg"})
public class Result implements Serializable {
    private static final long serialVersionUID = 10L;
    protected int resultCode;
    protected String resultMsg;
    public int getResultCode() { return this.resultCode; }
    public void setResultCode(int value) { this.resultCode = value; }
    public String getResultMsg() { return this.resultMsg; }
    public void setResultMsg(String value) { this.resultMsg = value; }
}
package com.caiex.vb.model;

import java.io.Serializable;

public class Response implements Serializable {
    private static final long serialVersionUID = 2360867989280235575L;
    private Result result;
    private Object data;
    public Result getResult() {
        if (this.result == null) { this.result = new Result(); }
        return result;
    }
    public void setResult(Result result) { this.result = result; }
    public Object getData() { return data; }
    public void setData(Object data) { this.data = data; }
}

3. Choose HTTP Method

Follow RESTful conventions: GET for reads, POST for creates, PUT/PATCH for updates, DELETE for removals.

4. Unified Return Codes

public static final int NO_AGENT_RATE = 1119; // rate not found
public static final int SCHEME_COMMIT_FAIL = 4000; // scheme submission failed
public static final int SCHEME_CONFIRMATION = 4001; // scheme confirming
public static final int SCHEME_NOT_EXIST = 4002; // scheme does not exist
public static final int SCHEME_CANCEL = 4005; // scheme cancelled
// ... other codes

5. Global Exception Handling

package com.caiex.vb.interceptor;

import javax.servlet.http.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.caiex.vb.model.Response;

@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @ExceptionHandler(value = Exception.class)
    public Response allExceptionHandler(HttpServletRequest request, Exception exception) {
        logger.error("Caught exception:", exception);
        Response response = new Response();
        response.setData(null);
        response.getResult().setResultCode(9999);
        response.getResult().setResultMsg("System busy");
        return response;
    }
}

6. Interceptor Chain

Use Spring MVC interceptors to validate signatures, rate‑limit requests, and enforce common parameters.

package com.caiex.vb.interceptor;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import com.alibaba.fastjson.JSON;
import com.caiex.redis.service.api.RedisApi;
import com.caiex.vb.model.Response;
import com.caiex.vb.utils.CaiexCheckUtils;

@Component
public class SignInterceptor extends BaseValidator implements HandlerInterceptor {
    private Logger logger = LogManager.getLogger(this.getClass());
    @Resource
    private RedisApi redisApi;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (isTestIpAddr(request)) { return true; }
        String securityKey = redisApi.hGet("securityKey", request.getParameter("agentid"));
        if (StringUtils.isEmpty(securityKey)) {
            Response resp = new Response();
            resp.setData(null);
            resp.getResult().setResultCode(8001);
            resp.getResult().setResultMsg("Missing private key, channel: " + request.getParameter("agentid"));
            logger.error("Missing private key, channel: " + request.getParameter("agentid"));
            InterceptorResp.printJson(response, resp);
            return false;
        }
        String sign = request.getParameter("sign");
        if (StringUtils.isEmpty(sign) || !sign.equals(CaiexCheckUtils.getSign(request.getParameterMap(), securityKey))) {
            Response resp = new Response();
            resp.setData(null);
            resp.getResult().setResultCode(3203);
            resp.getResult().setResultMsg("Signature verification failed");
            logger.error("Signature verification failed: " + JSON.toJSONString(request.getParameterMap()) + " securityKey=" + securityKey);
            InterceptorResp.printJson(response, resp);
            return false;
        }
        return true;
    }
    // afterCompletion and postHandle omitted for brevity
}

7. Spring MVC Configuration

package com.caiex.oltp.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import com.caiex.oltp.interceptor.*;

@EnableWebMvc
@Configuration
@ComponentScan
public class WebAppConfigurer extends WebMvcConfigurerAdapter {
    @Bean
    public CommonValidator commonInterceptor() { return new CommonValidator(); }
    @Bean
    public DDSAuthValidator ddsAuthInterceptor() { return new DDSAuthValidator(); }
    @Bean
    public QueryPriceParamsValidator queryPriceParamsInterceptor() { return new QueryPriceParamsValidator(); }
    @Bean
    public TradeParamsValidator tradeParamsInterceptor() { return new TradeParamsValidator(); }
    @Bean
    public APILimitRateValidator aPILimitRateInterceptor() { return new APILimitRateValidator(); }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(aPILimitRateInterceptor()).addPathPatterns("/*/*");
        registry.addInterceptor(ddsAuthInterceptor())
                .addPathPatterns("/tradeState/*", "/recycle/*", "/matchInfo/*", "/price/tradeTicketParam");
        registry.addInterceptor(commonInterceptor())
                .addPathPatterns("/price/tradeTicketParam", "/tradeState/*", "/recycle/*");
        registry.addInterceptor(queryPriceParamsInterceptor()).addPathPatterns("/price/getPriceParam");
        registry.addInterceptor(tradeParamsInterceptor()).addPathPatterns("/price/tradeTicketParam");
        super.addInterceptors(registry);
    }
}

8. Token Generation and Signature

Provide a token‑creation endpoint for third‑party callers. Tokens expire after one day; repeated requests within a minute return the same token to ease consistency.

private String createToken() {
    String utk = "Msk!D*" + System.currentTimeMillis() + "UBR&FLP";
    logger.info("create token --- " + Md5Util.md5(utk));
    return Md5Util.md5(utk);
}

Signature algorithm: concatenate parameterName + parameterValue + privateKey for every non‑null parameter, then MD5 the string. Verification repeats the process and compares the result with the supplied sign value.

Improving API Concurrency and Availability

Load Balancing

Deploy Alibaba Cloud SLB in front of a Kubernetes (k8s) cluster. The k8s service exposes internal load‑balancing, and the external SLB distributes traffic across the nodes.

Clustering

When a single service becomes a bottleneck, add more instances. If the bottleneck shifts to message queues, increase consumer instances or adjust broker configurations to balance producer‑consumer rates.

Caching

Cache slow‑to‑fetch data in Redis or an in‑process ConcurrentHashMap with expiration. Use batch operations like mGet to reduce round‑trips.

Cache objects in ConcurrentHashMap with TTL.

Store rarely‑changing keys in Redis and refresh via scheduled tasks.

Batch fetch multiple keys with mGet to improve throughput.

High‑Availability Architecture

Address single‑point failures by employing Redis master‑slave replication, ZooKeeper‑managed Dubbo clusters, and Storm master‑slave setups.

Idempotency and Order Uniqueness

Use Redis SETNX with a short TTL (e.g., 3 seconds) to lock an order ID during processing, preventing duplicate submissions while allowing retries after a failure.

Timeout Handling

If processing exceeds 10 seconds, automatically mark the transaction as failed and return an error response.

Conclusion

Effective API design requires clear contracts, unified response formats, robust exception handling, and a layered interceptor strategy. Scaling for high concurrency involves load balancing, clustering, caching, and rate limiting, while high availability demands redundant services and careful handling of idempotency and timeouts.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Exception Handlingload balancinghigh concurrencyapi-designtoken security
Code Ape Tech Column
Written by

Code Ape Tech Column

Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.