Commit de3fd791 authored by wutu's avatar wutu

实现部分集群服务的功能

parent fdfd2146
/bishe-edge-center/target/ /bishe-edge-center/target/
*.iml
# Default ignored files
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
\ No newline at end of file
...@@ -46,6 +46,15 @@ ...@@ -46,6 +46,15 @@
<version>1.0-SNAPSHOT</version> <version>1.0-SNAPSHOT</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>
\ No newline at end of file
...@@ -5,8 +5,10 @@ import org.mybatis.spring.annotation.MapperScan; ...@@ -5,8 +5,10 @@ import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@EnableScheduling
@MapperScan("top.ninwoo.edgecenter.dao") @MapperScan("top.ninwoo.edgecenter.dao")
public class EdgeCenterApp { public class EdgeCenterApp {
public static void main(String[] args) { public static void main(String[] args) {
......
...@@ -3,7 +3,7 @@ package top.ninwoo.edgecenter.controller; ...@@ -3,7 +3,7 @@ package top.ninwoo.edgecenter.controller;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import top.ninwoo.utils.service.DockerService; import top.ninwoo.edgecenter.service.ClusterService;
import java.util.List; import java.util.List;
...@@ -11,12 +11,11 @@ import java.util.List; ...@@ -11,12 +11,11 @@ import java.util.List;
public class IndexController { public class IndexController {
@Autowired @Autowired
DockerService dockerService; ClusterService clusterService;
@RequestMapping("/index") @RequestMapping("/index")
public List<String> index() { public List<String> index() {
dockerService.updateContainers(); List<String> containerIds = clusterService.getContainerIds();
List<String> dockerIds = dockerService.getDockerIds(); return containerIds;
return dockerIds;
} }
} }
package top.ninwoo.edgecenter.entity;
import lombok.Data;
import lombok.Getter;
import top.ninwoo.utils.entity.DockerContainer;
import java.util.Date;
import java.util.List;
/**
* @author joliu
* @date 2019-10-20
* @description 集群的配置类
*/
@Data
public class ClusterConfig {
private long id;
private Date createTime;
private String owner;
private List<ContainerDescription> dockers;
}
package top.ninwoo.edgecenter.entity;
import lombok.Data;
import top.ninwoo.utils.entity.DockerContainer;
import java.util.Date;
/**
* @Author joliu
* @Description 容器具体的描述信息
* @Date Create in 下午2:17 2019/10/20
*/
@Data
public class ContainerDescription {
private String mode;
private int replicas;
// dockerContainer模板
private DockerContainer dockerContainer;
}
package top.ninwoo.edgecenter.entity; package top.ninwoo.edgecenter.entity;
import lombok.Data;
/**
* @Author joliu
* @Description
* @Date Create in 下午2:17 2019/10/20
*/
@Data
public class User { public class User {
private long userId; private long userId;
private String password; private String password;
public long getUserId() {
return userId;
}
public void setUserId(long userId) {
this.userId = userId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
} }
package top.ninwoo.edgecenter.scheduler;
/**
* @author joliu
* @description 定时任务
*/
public interface Scheduler {
void update();
}
package top.ninwoo.edgecenter.service;
import top.ninwoo.edgecenter.entity.ClusterConfig;
import java.util.List;
import java.util.Set;
public interface ClusterService {
// 获取容器列表
List<String> getContainerIds();
// 创建容器组
long initContainers(ClusterConfig clusterConfig);
// 获取集群列表
Set<Long> getClusterIds();
// 通过集群Id获取集群中包含的容器IDs
Set<String> getContainerIdsByClusterId(long clusterId, String containerName);
void removeContainersByClusterId(long clusterId);
void removeContainersByClusterIdAndContainerName(long clusterId, String name);
}
package top.ninwoo.edgecenter.service;
public interface NetworkService {
}
package top.ninwoo.edgecenter.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import top.ninwoo.edgecenter.entity.ClusterConfig;
import top.ninwoo.edgecenter.entity.ContainerDescription;
import top.ninwoo.edgecenter.scheduler.Scheduler;
import top.ninwoo.edgecenter.service.ClusterService;
import top.ninwoo.utils.entity.DockerContainer;
import top.ninwoo.utils.service.DockerService;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author joliu
* @date 2019-10-18
* @description 集群服务类
*/
@Service
public class ClusterServiceImpl implements ClusterService, Scheduler {
private ConcurrentHashMap<Long, Map<String, Set<String>>> clustersInfo = new ConcurrentHashMap<>();
@Autowired
DockerService dockerService;
@Scheduled(fixedRate = 5000)
@Override
public void update() {
dockerService.updateContainers();
}
@Override
public List<String> getContainerIds() {
return dockerService.getDockerIds();
}
/**
* @description 创建容器组
* @param clusterConfig
* @return
*/
@Override
public long initContainers(ClusterConfig clusterConfig) {
// 校验ClusterConfig是否符合要求
if(clusterConfig.getId() == 0L) {
// 需要保存到数据库中,获取全局唯一的集群id
saveClusterConfig(clusterConfig);
}
if(clustersInfo.containsKey(clusterConfig.getId())) {
clustersInfo.get(clusterConfig.getId()).clear();
} else {
clustersInfo.put(clusterConfig.getId(), new HashMap<String, Set<String>>());
}
// 启动容器
List<ContainerDescription> dockers = clusterConfig.getDockers();
dockers.forEach(c -> {
// 创建docker的逻辑
// TODO: 根据Mode选择不同的模式
// 根据副本数量创建多少个容器
if(c.getReplicas() <= 0) {
// do nothing
} else {
DockerContainer containerConfig = c.getDockerContainer();
String containerName = containerConfig.getName();
// 校验Container名称是否唯一
if(clustersInfo.get(clusterConfig.getId()).containsKey(containerName)) {
throw new RuntimeException("Container Name must be unique!");
}
clustersInfo.get(clusterConfig.getId()).put(containerName, new HashSet<>());
for (int i = 0; i < c.getReplicas(); i++) {
// 处理DockerContainer中的名称
if(!"".equals(containerConfig.getName())) {
containerConfig.setName(containerName+ "_" + i);
}
DockerContainer dockerContainer = dockerService.runDocker(containerConfig);
clustersInfo.get(clusterConfig.getId()).get(containerName).add(dockerContainer.getId());
}
}
});
clusterConfig.setCreateTime(new Date());
return clusterConfig.getId();
}
/**
* @description 保存配置文件到数据库
* @param clusterConfig
*/
public ClusterConfig saveClusterConfig(ClusterConfig clusterConfig) {
// TODO: 保存数据到数据库
clusterConfig.setId(11111L);
return clusterConfig;
}
@Override
public Set<Long> getClusterIds() {
return clustersInfo.keySet();
}
@Override
public Set<String> getContainerIdsByClusterId(long clusterId, String containerName) {
return clustersInfo.get(clusterId).get(containerName);
}
@Override
public void removeContainersByClusterId(long clusterId) {
clustersInfo.get(clusterId).keySet().forEach(
c -> removeContainersByClusterIdAndContainerName(clusterId, c)
);
}
@Override
public void removeContainersByClusterIdAndContainerName(long clusterId, String containerName) {
clustersInfo.get(clusterId).get(containerName).forEach(
c -> dockerService.deleteDockerById(c)
);
}
}
\ No newline at end of file
package top.ninwoo.edgecenter;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import top.ninwoo.edgecenter.entity.ClusterConfig;
import top.ninwoo.edgecenter.entity.ContainerDescription;
import top.ninwoo.edgecenter.service.ClusterService;
import top.ninwoo.utils.entity.DockerContainer;
import java.util.ArrayList;
import java.util.List;
/**
* @Author joliu
* @Description 测试ClusterService
* @Date Create in 下午4:02 2019/10/20
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class ClusterServiceTest {
@Autowired
ClusterService clusterService;
long clusterId = 12312l;
@Test
public void testInitContainers() {
// 构建一个容器组配置
ClusterConfig clusterConfig = new ClusterConfig();
clusterConfig.setId(clusterId);
clusterConfig.setOwner("joliu");
ContainerDescription containerDescription = new ContainerDescription();
containerDescription.setMode("normal");
containerDescription.setReplicas(2);
DockerContainer container = new DockerContainer();
container.setName("Run");
container.setCommand("sh");
container.setImage("joliu/networktest");
containerDescription.setDockerContainer(container);
List<ContainerDescription> cds = new ArrayList<>();
cds.add(containerDescription);
ContainerDescription containerDescription1 = new ContainerDescription();
containerDescription1.setMode("normal");
containerDescription1.setReplicas(3);
DockerContainer container1 = new DockerContainer();
container1.setName("APP");
container1.setCommand("sh");
container1.setImage("joliu/networktest");
containerDescription1.setDockerContainer(container1);
cds.add(containerDescription1);
clusterConfig.setDockers(cds);
long id = clusterService.initContainers(clusterConfig);
Assert.assertEquals(id, clusterId);
Assert.assertTrue(clusterService.getClusterIds().contains(clusterId));
System.out.println(clusterService.getContainerIdsByClusterId(clusterId, "APP"));
}
@Test
public void testRemoveContainers() {
clusterService.removeContainersByClusterId(clusterId);
// TODO: 实时更新容器列表
// TODO: 没有做边界条件判断
}
}
...@@ -103,11 +103,12 @@ public class DockerServiceImpl implements DockerService { ...@@ -103,11 +103,12 @@ public class DockerServiceImpl implements DockerService {
@Override @Override
public DockerContainer runDocker(DockerContainer container) { public DockerContainer runDocker(DockerContainer container) {
// TODO: 这里启动Docker容器,需要再研究port如何起作用 // TODO: 这里启动Docker容器,需要再研究port如何起作用
// TODO: 这里还需要处理name等属性为空的情况
String cmd = "docker run -itd --name " + container.getName() + " " + container.getImage() + " " + container.getCommand(); String cmd = "docker run -itd --name " + container.getName() + " " + container.getImage() + " " + container.getCommand();
String result = linuxService.runCmd(cmd); String result = linuxService.runCmd(cmd);
if(result.contains("Error")) { if(result.contains("Error")) {
throw new RuntimeException("Run Docker failed!"); throw new RuntimeException("Run Docker failed!:" + cmd);
} }
// TODO:需要从Docker中查询处完整的信息 // TODO:需要从Docker中查询处完整的信息
container.setId(result); container.setId(result);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment