# vts-parent
**Repository Path**: wangscript/vts-parent
## Basic Information
- **Project Name**: vts-parent
- **Description**: 整车服务化
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2017-11-09
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 整车微服务框架教程
### *前言*
---
整车微服务框架是一个偏业务的框架,它把整车下单/询价/中转/中标/查询/权限等服务进行了一定的抽象,然后又添加了服务发现和路由配置的功能,支持把项目最小化,每一个项目只实现几个服务,减少开发启动项目的时间成本。所以最终可能会产生几十上百个war包,这些war包可以部署到一个jboss服务下,不会对上线产生太大的影响,也不会增加部署难度。
整车微服务框架的几个组件:
- 注册中心(zookeeper或者注册应用服务)
- 路由中心(console管理控制台,后续会添加新功能)
- 统一缓存(redis或ehcache集群)
- RPC客户端应用(部署十个左右,通过A10 虚拟IP访问,dev/sit/uat环境部署一个,一次部署,以后不需要发生变更)
- 服务端应用(部署十个Jboss,每个jboss几十个war)
- EasyOps(ELK)统一日志收集中心
#【微服务的架构模式下,要注意服务的幂等性】
【应用部署顺序】
注册中心 > 路由中心 > 缓存服务器 > MyCat数据库中间件 > ELK > 客户端 > 服务端
【优点】:
除了变更注册中心地址来切换环境,开发不需要维护和微服务有关系的任何组件和配置。
测试环境出问题,开发可以切换环境,由测试直接发起请求调试测试环境出的BUG,开发不需要模拟操作
项目应用启动速度快,启动基本在10秒左右。
项目低耦合,和自己无关的项目,开发都不需要导入,eclipse中维护当前使用的几个小项目就可以了。提高eclipse启动和运行速度。
支持异步响应,把一些耗时的,影响小操作放在响应之后执行,提高响应速度,体验好。
采用TCC分布式事务,最大可能的保证分布式调用的数据一致性
### *项目结构说明*
---
项目结构相当简单
+ `vts-config` 存放环境配置
+ `vts-db` Dao单表操作模块,开发添加新表时才需要操作,平时不需要修改
+ `vts-base` 存放业务抽象类
+ 其他为开发自建的具体服务模块(vts-login/vts-funny是演示服务开发用)
### *怎么建立新的微服务模块?*
---
1.右击vts-parent 建立 maven module web项目
2.修改pom.xml添加如下内容
com.deppon.vts
vts-base
0.0.1-SNAPSHOT
javax.servlet
servlet-api
${servlet.version}
provided
javax.servlet
jsp-api
${jsp.version}
provided
login
maven-war-plugin
3.0
org.apache.tomcat.maven
tomcat7-maven-plugin
2.1
src/main/webapp/WEB-INF/context.xml
8882
/login
false
3.修改web.xml
contextConfigLocation
classpath*:core.xml
org.springframework.web.context.ContextLoaderListener
4.在WEB-INF目录下新建context.xml,添加数据源JNDI配置
WEB-INF/web.xml
OK,新项目就需要以上四步操作。
###*如何抽象一个新的通用服务 ?*
---
1.在**`vts-base`**项目中写一个抽象类继承`PublicBizBaseService`类,同时自己定义`RequestEntity` / `ResponseEntity`请求响应实体, 实现`IExecuteService`接口,在接口中重写INTERFACE字段值
不可使用AL/BG/CM/DT/OR/QY/QE,这些是框架既定的编码,用于固定的业务流程,在生产环境下会使用dubbo对这些服务进行性能配置管控。
public abstract class LogicExecuteService extends PublicBizBaseService implements IExecuteService{
public LogicExecuteService(){
//该服务的子类配置msgId时必须以EE开头
INTERFACE = "EE";
}
@Override
public void process(BizContext ctx) throws Exception {
LogicExecuteRequestEntity request = (LogicExecuteRequestEntity) ctx.getRequest();
LogicExecuteResponseEntity response = (LogicExecuteResponseEntity) ctx.getResponse();
//TODO 这里完善服务的通用逻辑
{
if(log.isDebugEnabled()){
log.debug("LogicExecuteService is processing for msgId: {}",this.getMsgId());
}
}
super.process(ctx);
}
}
2.重写process方法,在该方法中对一类业务的通用操作进行抽象,比如该抽象类的子类都需要获取用户信息,那么在该方法中统一获取用户信息,然后调用 `super.process(ctx)`
### *如何实现一个业务 ?*
---
举例:比如车辆到达接口,在车辆到达时抽象服务LogicArrivalService
会统一变更车辆以及订单的状态,在做个体车到达接口时,开发只需要写通用服务中没有的业务逻辑比如:发起基站定位。
######1 编写业务代码
@Logic
public class PersonalArrivalLogicService extends LogicArrivalService {
private Logger log = LoggerFactory.getLogger(PersonalArrivalLogicService.class);
// 通用Mapper,因为使用缓存,强制大家使用单表查询,单表对后期做分库分表也有利
@Autowired
private TVmVehicleMapper tVmVehicleMapper;
public void processRequest(
BizContext context)
throws BizException {
log.info("车辆 {} 发起到达请求", context.getRequest().getVehicleNo());
Example example = new Example(TVmVehicle.class);
example.createCriteria().andCondition("vehicleNo = "+context.getRequest().getVehicleNo());
tVmVehicleMapper.selectByExample(example);
//TODO 发起基站定位
//设置响应消息
context.getResponse().setErrCode("0");
context.getResponse().setErrMsg("成功");
//返回数据给前台(支持返回sendXml, sendDownload, sendJson, sendImage, sendText)
sendJson(context);
//实现异步操作,在消息返回前台后,这里可以写一些比较耗时的业务操作
doSomeThing();
}
}
######2 服务的一些配置说明
---
配置服务信息
@Logic(title="",msgId="", baffle=false, permission={}, transactional=true, paramParser={})
public class FunnyLogicService extends LogicQueryService{
+ title 服务功能描述
+ msgId 服务编码;默认是Service的INTERFACE字段值(到父类中查找)+@+类名首字母小写
+ baffle 模拟开关; 设置为true时,执行业务类的processBaffle方法而不走processRequest方法,用来在开发时为调用方提供虚拟响应,不影响前端的开发进度
+ permission 设置用户需要哪些许可才能访问该服务,还没做这个权限功能,预留的
+ transactional 设置该服务是否开启事务 true:开启 false:不开启 (开关同时影响独立事务和TCC分布式事务)
+ paramParser 自定义参数解析器,默认框架只解析基本数据类型的参数,复杂对象需要开发自己实现,允许传入多个解析器
### *如何启动项目?*
---
1. 右击项目 `run as` -> `maven build`
2. 输入 `tomcat7:run`
3. 勾选 `Resolve Workspace artifacts`
4. 启动 `run`
### *服务的请求地址是多少?*
---
1. [http://10.230.27.24:8180/client/api/msgs/服务编号](http://10.230.27.24:8180/client/api/msgs/服务编号)
2. [http://10.230.27.24:8180/client/api/msgs](http://10.230.27.24:8180/client/api/msgs);设置请求头msgId:服务编号
### *同时访问多个微服务的方式?*
---
1. [http://10.230.27.24:8180/client/api/msgs/服务编号1,服务编号2...](http://10.230.27.24:8180/client/api/msgs/服务编号)
2. [http://10.230.27.24:8180/client/api/msgs](http://10.230.27.24:8180/client/api/msgs);设置请求头msgId:服务编号1,服务编号2...
【整车微服务框架提升用户体验的两个异步措施】:
> 1. 把互相没有前后依赖的操作分布到不同的微服务中,调用方调用时同时执行。
> 比如原来一个业务操作需要经过操作A,B,C,D四个步骤,对应的执行时间分别为1,2,3,4秒,普通的调用方式执行时间一共是1+2+3+4=10秒;
> 采用微服务批量调用的方式执行时间为最长的操作时间为4秒;
>
> 2. 在一个微服务中,允许开发异步响应前端,把资源检查等保证安全性的操作提前,验证无误后直接响应前台,把一些耗时的操作放在响应之后,此时响应时间基本可以做到减少50%左右
### *服务怎么配置路由?*
---
[http://10.230.27.24:8280/console/](http://10.230.27.24:8280/console/ "开发环境路由配置")
- 服务编码填写spring配置中的msgId
- 主机地址填写服务的目标IP
- 有效期是这条路由信息的有效期,失效就需要重新配置
注意事项:
> 开发新接口时,不需要配置路由,因为新服务只有你自己有。
> 代码提交以后,所有请求优先会进入测试服务器(通过路由中心配置通配符实现),如果测出问题,通过路由配置转到开发本机。
### *查看应用调用日志信息*
---
[http://10.230.27.28:5601/](http://10.230.27.28:5601/ "Kibana日志查询")
### *更改注册中心配置*
---
在vts-config项目下修改src/main/config目录下的dubbo.properties文件:
#####dubbo.registry.protocol=zookeeper
#####dubbo.registry.address=10.230.27.24:2181,10.230.27.24:2182,10.230.27.24:2183
【不要使用】
#####dubbo.registry.address=zookeeper://10.230.27.24:2181?backup=10.230.27.24:2182,10.230.27.24:2183
### *开启mybatis二级缓存*
---
方案1. 对于需要开启缓存的表 修改mybatis的mapper文件
方案2. 对于需要开启缓存的表 修改mybatis的mapper接口
@CacheNamespace(implementation=com.deppon.vts.data.plugin.MyBatisRedisCache.class)
public interface TVmVehicleMapper extends Mapper{
}
> 切记使用单表操作,因为二级缓存在同一个命名空间下有效,如果有关联,会因为修改了其他命名空间下的表,却没有发起缓存更新通知,导致对方缓存没有及时更新。