基于Kubernetes、Docker的机器学习微服务系统设计系列——(三)RESTful微服务框架

本文介绍了如何在基于Kubernetes和Docker的机器学习微服务系统中,利用Jersey框架实现RESTful接口。通过RESTful设计,实现业务服务与通信解耦,保证接口交互的一致性。配置文件和资源类的详细说明展示了框架的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 内容提要

基于Kubernetes、Docker的机器学习微服务系统设计
实践篇(1)概念与构想(二)架构与部署(三)微服务框架(四)中文分词(五)预处理
(六)特征选择(七)分类器微(八)部署配置(九)应用服务(十)数据可视化
研究篇RS中文分词MP特征选择NLV文本分类快速kNN文本分类

  为了微服务的接口交互统一,本系统采用统一的框架模式。采用Jersey软件框架,Jersey 是开源的RESTful框架, 实现了JAX-RS (JSR 311 & JSR 339) 规范。

微服务框架

  RESTful框架实现流程如图所示:

RESTful框架实现流程图

  高层次的适配器模式的应用,将业务服务与RESTful通信解耦,业务仅关注自己的实现。

框架实现

  配置文件config.properties内容如下:

#restful API config
listen.ip=0.0.0.0
listen.port=8084

#thread pool config
thread.core.pool.size=4
thread.max.pool.size=4

#mirco server config
mircoServer.name=business
jar.path=file:business-1.0.jar
jar.actionClass=com.robin.action.BusinessAction

#log config
log.path=log/
log.prefix=business
# Level.ALL Level.FINEST Level.FINER Level.FINE Level.CONFIG 
# Level.INFO Level.WARNING Level.SEVERE Level.OFF
log.level=Level.INFO
log.file.limit=1048576
log.file.count=3

  通用资源类:

/**
 * <DT><B>描述:</B></DT>
 * <DD>通用资源类</DD>
 *
 * @version Version1.0
 * @author  Robin
 * @version <I> V1.0 Date:2018-05-21</I>
 * @author  <I> E-mail:xsd-jj@163.com</I>
 */
@Path("robin")
public class CommonResource {
    // 日志
    private static final Logger LOGGER = RobinLogger.getLogger();
    // 微服务
    private static MircoServiceAction mircoServer;
    // 配置的微服务名称
    private static final String CFG_MS_NAME;

    static {
        // 微服务名称配置文件检查
        CFG_MS_NAME = ConfigUtil.getConfig("mircoServer.name");
        
        String jarPath = ConfigUtil.getConfig("jar.path");
        URL url = null;
        try {
            url = new URL(jarPath);
        } catch (MalformedURLException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage());
        }

        URLClassLoader classLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread()
                .getContextClassLoader());
        Class<?> actionClass = null;
        try {
            String actionClassName = ConfigUtil.getConfig("jar.actionClass");
            actionClass = (Class<?>) classLoader.loadClass(actionClassName);
        } catch (ClassNotFoundException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage());
        }
        if (null == actionClass) {
            LOGGER.log(Level.SEVERE, "actionClass is null");
            System.exit(-1);
        }
        try {
            mircoServer = (MircoServiceAction) actionClass.newInstance();
        } catch (InstantiationException | IllegalAccessException ex) {
            LOGGER.log(Level.SEVERE, ex.getMessage());
        }
    }

    /**
     * Method handling HTTP GET requests. The returned object will be sent to
     * the client as "application/json" media type.
     *
     * @return String that will be returned as a application/json response.
     */
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public String getIt() {
        String cfgMsName = ConfigUtil.getConfig("mircoServer.name");
        return "Micro server [" + cfgMsName + "] is running...\n";
    }

    @POST
    @Path("{microService}")
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public JSONObject requestService(
            @PathParam("microService") String serverName,
            JSONObject reqJson) {
        JSONObject rspJson = null;
        if (!serverName.equals(CFG_MS_NAME)) {
            rspJson = new JSONObject();
            try {
                rspJson.put("status", "ERROR");
                rspJson.put("msg", "Mirco server name [" + serverName + "] error.");
            } catch (JSONException ex) {
                LOGGER.log(Level.SEVERE, ex.getMessage());
            }
            return rspJson;
        }

        if (null != mircoServer) {
            rspJson = (JSONObject) mircoServer.action(reqJson);
        }

        return rspJson;
    }
}

  Restful服务类:

/**
 * <DT><B>描述:</B></DT>
 * <DD>Restful服务类</DD>
 *
 * @version Version1.0
 * @author  Robin
 * @version <I> V1.0 Date:2018-05-22</I>
 * @author  <I> E-mail:xsd-jj@163.com</I>
 */
public class RestfulServer {

    private static final Logger LOGGER = RobinLogger.getLogger();
    private static URI uri;
    private static HttpServer server;

    public static HttpServer getServer() {
        return server;
    }

    public static URI getUri() {
        if (null == uri) {
            String listenAddr = ConfigUtil.getConfig("listen.ip");
            String listenPort = ConfigUtil.getConfig("listen.port");
            String baseUri = "http://" + listenAddr + ":" + listenPort + "/";
            uri = URI.create(baseUri);
        }
        return uri;
    }

    /**
     * Starts Grizzly HTTP server exposing JAX-RS resources defined in this application.
     *
     */
    public static void startServer() {
        // create a resource config that scans for JAX-RS resources and providers
        // in com.robin.restful package
        final ResourceConfig rc = new ResourceConfig();
        rc.packages("com.robin.restful");
        rc.register(JettisonFeature.class);

        // create and start a new instance of grizzly http server
        // exposing the Jersey application at URI
        // return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI), rc);
        server = GrizzlyHttpServerFactory.createHttpServer(getUri(), rc);

        String corePoolSizeStr = ConfigUtil.getConfig("thread.core.pool.size");
        String maxPoolSizeStr = ConfigUtil.getConfig("thread.max.pool.size");
        int corePoolSize = 0;
        int maxPoolSize = 0;
        if ((corePoolSizeStr != null) && (!corePoolSizeStr.equals(""))) {
            corePoolSize = Integer.valueOf(corePoolSizeStr);
        }

        if ((maxPoolSizeStr != null) && (!maxPoolSizeStr.equals(""))) {
            maxPoolSize = Integer.valueOf(maxPoolSizeStr);
        }

        if ((corePoolSize == 0) || (maxPoolSize == 0)) {
            LOGGER.log(Level.INFO, "Use default thread pool configuration.");
            return;
        }

        if ((corePoolSize > maxPoolSize)) {
            LOGGER.log(Level.SEVERE, "Core pool size greater than max pool sixe in configuration.");
            LOGGER.log(Level.INFO, "Use default thread pool configuration.");
            return;
        }

        //参考http://jersey.576304.n2.nabble.com/It-s-very-hard-to-increase-the-number-of-worker-threads-in-Jersey-Grizzly-module-td7579570.html
        NetworkListener nl = server.getListener("grizzly");
        System.out.println(nl.toString());
        TCPNIOTransport transport = nl.getTransport();
        ThreadPoolConfig config = transport.getWorkerThreadPoolConfig();
        config.setCorePoolSize(corePoolSize);
        String info = "Set thread core pool size [" + corePoolSize + "].";
        LOGGER.log(Level.INFO, info);
        config.setMaxPoolSize(maxPoolSize);
        info = "Set thread max pool size [" + maxPoolSize + "].";
        LOGGER.log(Level.INFO, info);
        GrizzlyExecutorService threadPool = (GrizzlyExecutorService) transport.getWorkerThreadPool();
        threadPool.reconfigure(config);
    }

    /**
     * RestfulServer method.
     *
     * @param args
     */
    public static void main(String[] args) {
        startServer();
        if (server.isStarted()) {
            LOGGER.log(Level.INFO, "Start http server sucessfully.");
        } else {
            LOGGER.log(Level.SEVERE, "Start http server failed.");
        }
    }
}

  微服务入口Action接口

package com.robin.loader;
/**
 * <DT><B>描述:</B></DT>
 * <DD>微服务入口Action接口</DD>
 *
 * @version Version1.0
 * @author Robin
 * @version <I> V1.0 Date:2018-05-04</I>
 * @author  <I> E-mail:xsd-jj@163.com</I>
 */
public interface MircoServiceAction {
    public Object action(Object obj);
}
知更鸟博文推荐
上一篇 基于Kubernetes、Docker的机器学习微服务系统设计系列——(二)架构与部署
下一篇 基于Kubernetes、Docker的机器学习微服务系统设计系列——(四)中文分词微服务
推荐篇 基于Kubernetes、Docker的机器学习微服务系统设计——完整版
研究篇 RS中文分词   |  MP特征选择   |  NLV文本分类   |  快速kNN
作者简介
兴趣爱好机器学习、云计算、自然语言处理、文本分类、深度学习
E-mailxsd-jj@163.com (欢迎交流)
版权声明:个人原创,请勿抄袭,欢迎引用,未经许可禁止转载. © 知更鸟
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值