# 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{ } > 切记使用单表操作,因为二级缓存在同一个命名空间下有效,如果有关联,会因为修改了其他命名空间下的表,却没有发起缓存更新通知,导致对方缓存没有及时更新。