一、概述
创建
app
流程
二、创建流程
1.页面操作
示例如下:
2.后台代码:
AppController#apps
方法
在接到请求后,首先将app对象转成model对象,然后写库,发布app创建的事件出去。
public App create(@Valid @RequestBody AppModel appModel) {
//将AppModel转成App对象
App app = transformToApp(appModel);
//保存App对象到数据库
App createdApp = appService.createAppInLocal(app);
//发布AppCreationEvent创建事件
publisher.publishEvent(new AppCreationEvent(createdApp));
//授予 App 管理员的角色
Set<String> admins = appModel.getAdmins();
if (!CollectionUtils.isEmpty(admins)) {
rolePermissionService.assignRoleToUsers(RoleUtils.buildAppMasterRoleName(createdApp.getAppId()),
admins, userInfoHolder.getUser().getUserId());
}
//返回app对象
return createdApp;
}
CreationListener#onAppCreationEvent
在上面创建完成后会广播出来一个事件,事件的消费者如下,这里就会发送http请求到Admin Server,对应
adminservice
服务中AppController#create
@EventListener
public void onAppCreationEvent(AppCreationEvent event) {
// 将 APP 转成 AppDTO 对象
AppDTO appDTO = BeanUtils.transform(AppDTO.class, event.getApp());
// 获取有效的 Env 数组
List<Env> envs = portalSettings.getActiveEnvs();
//循环 Env 数组,调用对应的Admin Service 的 API , 创建App 对象
for (Env env : envs) {
try {
appAPI.createApp(env, appDTO);
} catch (Throwable e) {
logger.error("Create app failed. appId = {}, env = {})", appDTO.getAppId(), env, e);
Tracer.logError(String.format("Create app failed. appId = %s, env = %s", appDTO.getAppId(), env), e);
}
}
}
AppController#create
@PostMapping("/apps")
public AppDTO create(@Valid @RequestBody AppDTO dto) {
App entity = BeanUtils.transform(App.class, dto);
//如果appId已经存在,那重复了就抛出异常
App managedEntity = appService.findOne(entity.getAppId());
if (managedEntity != null) {
throw new BadRequestException("app already exist.");
}
//保存 App 对象到数据
entity = adminService.createNewApp(entity);
//将保存的 App 对象,转换成 AppDTO 返回
return BeanUtils.transform(AppDTO.class, entity);
}
AdminService#createNewApp
这里会创建默认的
namespace
和cluster
// 保存 App 对象到数据库
String createBy = app.getDataChangeCreatedBy();
App createdApp = appService.save(app);
String appId = createdApp.getAppId();
//创建 App 的默认命名空间 "application"
appNamespaceService.createDefaultAppNamespace(appId, createBy);
//创建 App 的默认集群 "default"
clusterService.createDefaultCluster(appId, createBy);
//创建 Cluster 的默认命名空间
namespaceService.instanceOfAppNamespaces(appId, ConfigConsts.CLUSTER_NAME_DEFAULT, createBy);
- 在上面发现保存app的时候会涉及到跨系统的交互,因为要写到两个不同的DB,Patrol在同步App到Admin Server的时候,可能会存在app存在于patrol,不存在于admin service中,Apollo是怎么解决的?
这里参考这个:官方解答
会在页面上会出现『补缺环境』和『补缺namespace』按钮,可以手动进行事后补偿。
总结
这里创建的时候设计到不同系统的同步,这种补偿策略可以参考,可以根据不同的场景来选择。