dubbo+apollo微服务开发指南

为了你们比较快速的开发微服务,规范dubbo,spring,mybatis,hessian,netty的版本和用法,我写了一个demo,下面对demo的功能作个简单的介绍,若有疑问的地方,能够私下问我java

微服务项目示例 整合了dubbo2.5.11+spring 4.3.10+mybatis3.4.6+sharding-jdbc1.5.4.1(分库分表客户端)+apollo(集中配置) 包括微服务的rpc调用,数据库的增删改查,分布式集群惟一命名,分布式id生成,数据分布算法(hash一致性+pre-shard)git

快速入门

下载源码

源码你能够从url获取:https://github.com/HowardYi/MicroServiceDemogithub

里面有一个spring-sharding-jdbc-example-mybatis-oracle子项目,你们导入maven项目便可web

准备环境

注意能访问到apollo 服务地址,oracle服务地址,zk服务地址,地址信息在配置文件中。须要本身打通这些服务依赖。算法

运行测试

MainProvider.java能够测试分库分表下的增删改查,主键和非主键路由算法测试,hint方式路由测试,分页排序功能测试,多表并发查询结果归并测试。 启动后提供dubbo服务,供下面MainProviderGateway.java应用调用,dubbo协议可调整。spring

MainProviderGateway.java启动后提供模拟的服务网关,对服务接口的封装,同时对外提供rest接口服务,swagger api定义,方便客户端在swagger ui上面进行接口定义查看,接口在线测试。sql

MainConsumer.java启动后,调用上面MainProviderGateway的接口,能够测试dubbo远程调用,rest协议方式。shell

DistributionInstanceNoAllocator.java测试集群惟一编号生成功能。数据库

DefaultIdGeneratorImpl.java测试雪花算法id生成功能。windows

ConsistedHashRouter.java测试一致性hash算法数据分布功能。

 

总体结构

依赖包结构

maven做为项目管理,提供编译,打包,组装发布的目录结构等功能;

dubbo2.5.11做为微服务框架,提供服务rpc,软负载均衡,容错重试,服务自动发现和注册,服务性能监控,服务可用性监测,后台管理的服务依赖,动态路由设置,动态参数调整,ip鉴权等功能,目前被dubbo_integration间接依赖进来,包括web容器启动dubbo支持,restful风格的接口swagger 功能支持,http/hessian3/hessian等协议的附件功能支持等;

spring 4.3.11做为业务逻辑层框架,提供ioc,aop容器,事务,配置等功能;

mybatis3.4.6+spring-mybatis1.3.2+pagehelper5做为持久层框架,提供dao自动生成,注解方式sql写法,分页排序支持等;

apollo0.10提供参数配置功能,不一样环境的参数配置,再也不须要maven的fliter功能,打不一样的部署包;

dbcp+ojdbc6提供数据源链接池和驱动;

slf4j+logback提供日志输出功能;

sharding-jdbc做为关系型数据的分布式客户端框架,提供hint方式和算法方式的路由,并发查询,结果排序分页统计;此功能在大部分项目能够忽略;

curator2.7.1做为访问zookeeper客户端;

 

代码结构

com.yspay.common.cluster应用实例机器惟一编号生成,动态生成惟一标识;

com.yspay.common.coordinator分布式协调器客户端,封装访问zk的代码;

com.yspay.common.datasource支持加密用户名和密码的数据源链接池;

com.yspay.common.idgenerator snowflake雪花算法做为惟一id生成器,取代oracle自增序列;

com.yspay.common.shard.consistedhash 一致性hash算法路由表,分库分表的算法;

com.yspay.sample.dubboprovider.api 应用服务对外的接口层;

com.yspay.sample.dubboprovider.datasource数据源层,分布式的数据源链接池;

com.yspay.sample.dubboprovider.entity业务实体层;

com.yspay.sample.dubboprovider.repository数据库持久层

com.yspay.sample.dubboprovider.service业务逻辑层;

 

经常使用功能用法开发指南

dubbo服务

配置

1,配置加载容器,应用信息,协议和日志等src\main\resources\dubbo.properties:

dubbo.container-》dubbo应用main方法启动时候加载哪些容器,目前配置有:spring,spring上下文加载,jetty,dubbo服务状态对外展现的web容器启动,logback,dubbo服务的日志组件初始化;

dubbo.application-》dubbo应用信息,管理控制台能够看到服务提供者信息;

dubbo.logback-》logback日志配置;

dubbo.protocol-》dubbo rpc协议配置,规定了通讯传输组件netty4,对象序列化方式hessian2,对外服务的ip(当有多个ip地址时须要指定)和端口,处理业务的工做线程池模型和数量,最大可链接客户端的数量;

jvm.heapdump.path-》jvm内存溢出时,堆栈导出目录

 

2,配置注册中心和性能监控src\main\resources\META-INF\spring\dubboCommonContext.xml:

<dubbo:registry protocol="zookeeper" client="curator" address="${dubbo.registry.address:10.213.32.120:2181}" />

<!--监控,测试环境和生产环境的时候打开-->
<dubbo:monitor protocol="registry"/>
 

编写dubbo服务代码和向注册中心注册服务

你能够编写一个spring bean (api层服务),而后加上下面简单配置便可:

配置文件src\main\resources\META-INF\spring\dubboProviderContext.xml

<dubbo:service interface="com.yspay.sample.dubboprovider.api.IOrderServiceApi" ref="orderServiceApiImpl"
protocol="dubbo" validation="false"></dubbo:service>

发布服务能够指定协议,指定注册中心等信息,具体细节参考dubbo开发指南。

 

从注册中心发现服务和引用远程服务

引入服务端发布的服务接口依赖包,而后加上下面配置便可:

src\main\resources\META-INF\spring\dubboConsumerContext.xml

<dubbo:reference id="orderServiceApiClient" interface="com.yspay.sample.dubboprovider.api.IOrderServiceApi"></dubbo:reference>

而后客户端代码就能够注入这个bean,调用远程服务了。

 

集中配置apollo指南

1,配置应用惟一标识,属性文件:src\main\resources\META-INF\app.properties

app.id-》指定应用在apollo配置中心的惟一标识,能够和dubbo应用名称一致

 

2,配置spring从配置中心加载哪些配置 src/main/resources/META-INF/spring/apolloContext.xml:

apollo以namespace为配置的最小集合单位,namespace包括一组配置(key=value形式配置单元),具体概念参考apollo官方用法

<!-- 这个是最简单的配置形式,通常应用用这种形式就能够了,用来指示Apollo注入application namespace的配置到Spring环境中 -->
<apollo:config order="3"/>

<!-- 这个是最复杂的配置形式,指示Apollo注入PAID.dubbo namespace的配置到Spring环境中,而且顺序在application前面 -->
<apollo:config namespaces="PAID.dubbo" order="2"/>

<apollo:config namespaces="PAID.datasource" order="1"/>

 

3,应用启动时指定当前环境:

jvm系统参数须要包括-Denv=dev或fat或uat或pro,指定当前运行环境,应用程序启动后根据这个值去集中配置服务取相关配置;

 

shell启动脚本会从操做系统环境变量获取这个evn参数,而后传递给jvm系统参数;

若是你运行Main进行测试,代码里面经过编码方式指定env:

// 设置环境变量env,apollo(集中配置)须要此变量
String env = System.getProperty("env");
if (env == null) {
System.setProperty("env", "FAT");
}

4,引用配置中心的参数值

下面是数据源的地址参数,不一样环境值不一样,使用${name:defaultvalue}方式

<bean id="ds_0" class="com.yspay.common.datasource.SecretBasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="${manager.url:jdbc:oracle:thin:@10.168.192.1:1521:orcl}"/>
<property name="username" value="${manager.username:defaultusername}"/>
<property name="password" value="${manager.password:defaultpwd}"/>
<property name="defaultAutoCommit" value="false"></property>
<property name="initialSize" value="${trade.inisize:3}"/>
<property name="maxActive" value="${trade.maxsize:10}"/>
<property name="minIdle" value="${trade.maxidle:2}" />
<property name="maxIdle" value="${trade.minidle:2}" />
<property name="validationQuery" value="select * from dual"/>
<property name="testWhileIdle" value="false" />
<property name="timeBetweenEvictionRunsMillis" value="600" />
</bean>

5,保证apollo配置文件本地备份目录有读写权限

apollo会在本地保存一份配置文件,防止不能访问远程配置服务的时候使用本地配置,默认会在/opt/data目录下,若是是windows是在c盘下这个目录;

 

业务逻辑层事务控制

1,配置事务管理器,以及注解方式事务管理:

src\main\resources\META-INF\spring\serviceContext.xml

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="shardingDataSource" />
</bean>
<tx:annotation-driven transaction-manager="transactionManager" />

2,代码中标注注解:

只读事务:

@Override
@Transactional(readOnly = true)
public void select() {
}

写事务,指示方法事务传播属性,根据异常类型回滚事务:

@Override
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
public void insert() {
}

持久层mybatis开发

1,配置

src\main\resources\META-INF\spring\mybatisContext.xml

配置mybatis session factory跟hibernate相似,这里面有一个pageInterceptor插件,用来生成分页sql的,具体用法能够参考pagehelper官网。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="shardingDataSource"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageInterceptor">
<property name="properties">
<!--使用下面的方式配置参数,一行配置一个 -->
<value>
helperDialect=oracle
rowBoundsWithCount=true
</value>
</property>
</bean>
</array>
</property>
</bean>

这个是配置自动生成dao(mybatis叫mapper)的实现类的,在basePackage下面的全部mapper接口,都会自动生成一个实现类bean,开发者不须要本身写dao的实现类,只须要定义dao接口以及dao接口须要使用的sql便可
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.yspay.sample.dubboprovider.repository"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
 

2,自动生成dao(mapper)代码和entity代码

2.1安装mybatis generator eclipse插件,

2.2编写代码自动生成工具须要的配置,主要是指定数据源,生成代码的目录,哪些表须要生成代码等等,项目中有一个配置文件例子:src\mybatis-generator-config\generatorConfig.xml,

2.3在eclipse里面,点击配置文件,右键菜单-》Run-》mybatis generator便可生成代码了

 

3, 编写定制的dao方法

上面自动生成的mapper方法一般不够知足本身的需求,定制mapper是必要的。

建立新mapper接口,通常不要再原来自动生成的mapper上进行修改,否则表改动后,从新生成mapper代码,会把你写的方法抹掉;我习惯在原来表mapper类的名字后加Ext表明是扩展的mapper。

类com\yspay\sample\dubboprovider\repository\OrderMapperExt.java,定义为自动生成类OrderMapper.java的扩展:

更新写法:

@Update({ "update T_ORDER ", "set STATUS = #{status,jdbcType=VARCHAR} ",
"where USER_ID = #{userId,jdbcType=VARCHAR} and ORDER_ID = #{orderId,jdbcType=VARCHAR}" })
int updateStatusByUserIdOrderId(Order record);

 

分页写法:
@Select({ "select", "ORDER_ID, USER_ID, STATUS, CREATE_DATE",
"from T_ORDER" })
@ResultMap("OrderMap")
List<Order> selectByPage(RowBounds row);

只要方法里面有RowBounds参数,sql会自动再加上分页的sql(rownum>? and rownum<?);因此上面查询sql并不须要分页相关的sql

相关文章
相关标签/搜索