当前位置: 首页 > Web前端 > HTML

技术分享-如何让上千个容器同时“存活”

时间:2023-03-28 19:25:58 HTML

最近接到一个请求,要求用户可以申请创建一个或多个docker容器,容器必须一直存在,用户可以访问不管多长时间,生成的数据存在每时每刻。也就是说,我们需要实现容器持久化。也就是说,我们需要提供一个小型的服务器,但是随着时间的推移,服务器资源会被容器占用,所以只能扩容。我想做的是提供尽可能多的docker容器,同时尽可能节省服务器。思路用户使用一段时间后,将用户产生的差异数据持久化,然后停止容器。当用户再次访问时,通过拦截访问地址创建一个新的容器,并将持久化的数据放入新的容器中,然后重定向。用户可以像以前一样访问同一个容器,就好像这个容器一直存在一样。实现过程1.当用户请求接口生成容器时,返回域名2.一段时间后,停止容器,配置下一次访问启动容器3.用户访问,通过上一次重启容器配置,并重定向回用户之前的数据下图所示的工具是支持docker-client的,因为我想用java来操作docker,启动,停止,删除,执行命令等,所以找了个快捷方式-使用工具。附上官网https://github.com/docker-jav...kongapi因为用户在访问容器中的接口时,如果容器已经被删除,就没有办法访问了,所以做了一个层在外层Proxy上,使用的工具是kongAPI,kong是基于nginx开发的APIGateway,可以通过代码控制,不需要像nginx那样手动修改配置文件。简单介绍一下我用到的几个函数:Route:是请求的转发规则,根据Hostname和PATH将请求转发给Service。(我理解的是nginx所在的位置)Services:是多个Upstreams的集合,是Route的转发目标。(我理解的是nginx的server)Plugin:就是插件。Plugin可以是全局的,绑定到Service,绑定到Router,绑定到Consumer。(里面有鉴权、访问限制、监控、日志等插件,我这里使用request-transformer,需要在请求中携带一些参数进行重定向)附上官网https://docs.konghq.com/详细实现1.生成容器当用户访问界面时,后台创建并启动容器,生成kong的配置。后续用户通过kong的代理访问容器,Route->Services->docker,设置心跳和过期时间,心跳是用户操作产生的,过期时间就是容器可以停止的时间。如果有心跳,就会更新过期时间。代码示例//创建容器CreateContainerCmdcreateContainerCmd=dockerClient.createContainerCmd(docker.getImage()).withTty(true).withName(this.generateContainerName(docker)).withCmd(managerUrl+docker.getId()).withHostConfig(hostConfig);CreateContainerResponsecontainerResponse=createContainerCmd.exec();//启动容器dockerClient.startContainerCmd(containerResponse.getId()).exec();二、停止容器停止容器是为了保证下一次用户访问请求时容器可以再次启动,所以容器停止后,用户访问容器的请求通过代理转发到后台接口,这里是代理港。具体步骤是后台会有一个job控制inactive容器持久化数据,然后停止容器,配置kong,让下一个请求分发到后台服务。具体实现:1、添加服务并设置http接口请求地址JKongAdminadmin=newJKongAdmin(kongAdminUrl);ServiceRespresp=admin.addService(newServiceReq.Builder().host(recoverHost).port(recoverPort).path(recoverPath).build());2。添加路由设置serviceId,用户访问域名JKongAdminadmin=newJKongAdmin(kongAdminUrl);RouteRespresp=admin.addRoute(newRouteReq.Builder().serviceId(serviceId).host(host).build());3.添加插件设置serviceId,后台地址主要用于重启容器就是带入参数JKongAdminadmin=newJKongAdmin(kongAdminUrl);MapreplaceConfigMap=newHashMap<>();replaceConfigMap.put("uri",recoverPath);PluginRespresp=admin.addPlugin(newPluginReq.Builder().name("request-transformer").serviceId(serviceId).config("replace",replaceConfigMap).e启用(真)。构建());3.重启容器。用户通过域名访问路由,路由转发给相应的服务。访问服务配置的http接口后,http接口启动容器,浏览器重定向,因为容器已经存在,只需要启动,速度可以达到秒级,从而实现“的错觉”容器@GetMapping("/recover")@ApiOperation(value="resourcerecovery")publicvoidrecover(HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{Stringhost=request.getHeader("x-forwarded-host");Stringpath=request.getHeader("x-forwarded-path");this.playgroundService.recover(主机);response.sendRedirect(host+":"+kongClientPort+path);}总结最后我们分析一下需求。其实主要难点在于容器停止后访问页面,然后再启动容器。因为用户访问容器绑定的域名,没有http接口,所以只能使用kongAPI拦截域名转发给后台服务器启动docker并重定向,停止空闲容器,保存内存,并在需要时重新启动它。通过处理,容器似乎一直处于启动状态。虽然后台有很多转发,但是首页没有任何感知。以上就是我今天要讲的内容。该技术主要使用kongAPI和docker-java。其实技术用起来没什么难度,主要是分享思路。