dubbo+apollo微服务开发指南

为了大家比较快速的开发微服务,规范dubbo,spring,mybatis,hessian,netty的版本和用法,我写了一个demo,下面对demo的功能做个简单的介绍,如有疑问的地方,可以私下问我

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

快速入门

下载源码

源码你可以从url获取:https://github.com/HowardYi/MicroServiceDemo

里面有一个spring-sharding-jdbc-example-mybatis-oracle子项目,大家导入maven项目即可

准备环境

注意能访问到apollo 服务地址,oracle服务地址,zk服务地址,地址信息在配置文件中。需要自己打通这些服务依赖。

运行测试

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

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

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

DistributionInstanceNoAllocator.java测试集群唯一编号生成功能。

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

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

 

 

转载于:https://my.oschina.net/u/3522232/blog/2251278

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值