SEO技术

SEO技术

Products

当前位置:首页 > SEO技术 >

如何避免在个人网站子域名中使用二级目录形式?

96SEO 2026-02-19 12:46 3


、分布式事务存在的问题二、分布式事务理论三、认识SeataSeata分布式事务解决方案1、XA模式2、AT模式3、SAGA模式4.SAGA模式优缺点5.四种模式对比

如何避免在个人网站子域名中使用二级目录形式?

四、微服务整合Seata

AT案例Seata配置微服务整合2.1、父工程项目创建引入依赖

新建seata-account-service微服务2.3.2引入依赖2.3.3seata事务用到的表2.3.4seata微服务配置2.3.5yml配置seata事务2.3.6数据源交给seata去代理2.3.7主启动类去掉默认自动加载数据源2.3.8业务数据dbDOdaoservicemapper.xmlcontroller

2.4、搭建库存微服务2.4.1

新建seata-storage-service微服务2.4.2引入依赖2.4.3seata事务用到的表2.4.4seata微服务配置2.4.5yml配置seata事务2.4.6数据源交给seata去代理2.4.7主启动类去掉默认自动加载数据源2.4.8业务数据dbDOdaoservicemapper.xmlcontroller

2.5、搭建订单微服务2.5.1

新建seata-order-service微服务2.5.2引入依赖2.5.3seata事务用到的表2.5.4seata微服务配置2.5.5yml配置seata事务2.5.6数据源交给seata去代理2.5.7主启动类去掉默认自动加载数据源2.5.8业务数据dbDOdaoserviceservice实现类添加GlobalTransactionalmapper.xmlfegincontroller

2.6、测试

在分布式系统下一个业务跨越多个服务或数据源每个服务都是一个分支事务要保证所有分支事务最终状态一致这样的事务就是分布式事务。

二、分布式事务理论

CAP是指Consistency(一致性Availability可用性Partition

tolerance分区容错性1、一致性

节点1的数据一旦发生修改节点2的数据必须进行同步与节点1的数据保持一致。

用户访问集群中的任意健康节点时必须能得到响应而不是超时或者拒绝。

当节点3发生故障时就会对请求进行阻塞或者拒绝此时节点3就是不可用的。

3、分区容错性

分区因为网络故障或其它原因导致分布式系统中的部分系欸DNA与其它节点失去连接形成独立分区。

起初节点1、2、3是互相连接的即任意节点数据发生变化其余两个节点的数据也将进行同步修改但是假设节点3与其他两个节点的网络连接断开了但是节点本身并没有故障就会形成新的分区此时一旦有人对节点2的数据进行了修改并将修改信息同步到了节点1此时用户访问不同的节点假设访问节点1之后我们又访问了节点3此时拿到的结果就是不一致的。

此时就不满足一致性如果我们非要满足一致性我们怎么办让节点3进入短暂的禁止访问状态等待和节点2的网络通信回复在此期间对于到来的一切请求都进行拒绝或者阻塞这样一来确实一致性问题得到了解决但是我们又说了可用性即系统健康时就必须对请求做出响应此时我们的节点3只是和其余两个节点不通并没有不健康所以这就是一种悖论我们只能在一致性和可用性之间做出抉择

CAP定理的主要内容分布式系统节点通过网络连接一定会出现分区问题P当分区出现时系统的一致性C和可用性A就无法同时满足CP保证了系统的一致性但是牺牲了系统的可用性。

BASE理论

BASE理论是对CAP的一种解决思路包含三个思想Basically

Available

基本可用分布式系统在出现故障时允许损失部分可用性即保证核心可用。

Soft

State软状态在一定时间内允许出现中间状态比如临时的不一致状态。

Eventually

Consistent最终一致性虽然无法保证强一致性但是在软状态结束后最终达到数据一致。

而分布式事务最大的问题是各个子事务的一致性问题因此可以借鉴CAP定理和BASE理论

AP模式各子事务分别执行和提交允许出现结果不一致软状态然后采用弥补措施恢复数据即可实现最终一致。

CP模式各个子事务执行后互相等待同时提交同时回滚达成强一致。

但事务等待过程中处于弱可用状态。

解决分布式事务各个子系统之间必须能感知到彼此的事务状态才能保证状态一致因此需要一个事务协调者来协调每一个事务的参与者子系统事务。

这里的子系统事务称为分支事务有关联的各个分支事务在一起称为全局事务。

三、认识Seata

事务管理器定义全局事务的范围、开始全局事务、提交或回滚全局事务。

(Resource

资源管理器管理分支事务处理的资源与TC交谈以注册分支事务和报告分支事务的状态并驱动分支事务提交或回滚。

Seata分布式事务解决方案

Seata提供了四种不同的分布式事务解决方案XA模式强一致性分阶段事务模式牺牲了一定的可用性无业务侵入TCC模式最终一致的分阶段事务模式有业务侵入AT模式最终一致的分阶段事务模式无业务侵入也是Seata的默认模式SAGA模式长事务模式有业务侵入1、XA模式

X/Open

描述了全局的TM与局部的RM之间的接口几乎所有主流的数据库都对

XA是规范目前主流的数据库都实现了这种规范实现的原理都是基于两阶段提交。

正常情况异常情况

本地事务执行完成后向事务协调者告知事务的执行状态此时本地事务并没有提交继续持有数据库锁

二阶段

事务协调者根据一阶段的报告判断下一步操作①、如果一阶段所有分支事务都执行成功则告知所有事务参与者提交事务。

②、如果一阶段任意一个事务失败则告知所有事务参与者回滚事务。

下面我们来看看Seata当中的XA模型

注册分支事务到TC

TC检测各分支事务的执行状态a.如果都成功通知所有RM提交事务b.如果有失败通知所有RM回滚事务RM二阶段的工作

优点事务的强一致性满足ACID原则。

常用数据库都支持实现简单并且没有代码侵入。

缺点因为一阶段需要锁定数据库资源等待二阶段结束才会释放性能较差。

依赖关系型数据库实现事务。

如何利用Seata实现XA模式

XA2、给发起全局事务的入口方法添加GlobalTransactional注解

3、重启服务测试

AT模式是对XA模式的弊端进行了完善执行事务完并不会持续占有数据库资源。

我们来看看AT模式具体是怎么做的

在XA模式当中一阶段分支事务执行完事务后会等待TC的通知进行事务的提交或者事务的回滚等待过程中会持有DB锁防止其他事务进行操作这样会大大降低性能在AT模式下分支事务不需要等待TC的通知即可提交事务但是会生成一份数据快照undo_log该快照记录了数据修改前和修改后的值当TC通知分支事务进行事务提交或者回滚时如果是提交分支事务则仅需要删除生成的快照即可如果是回滚则需要根据快照当中的信息恢复数据。

一阶段

XA模式一阶段不提交事务锁定资源AT模式一阶段直接提交不锁定资源。

XA模式依赖数据库机制实现回滚AT模式利用数据快照实现数据回滚。

解决方案就是引入全局锁的概念在释放DB锁之前先要拿到全局锁避免同一时刻有另外一个事务来操作当前持有的数据。

这个全局锁就限制了哪个事务可以操作该数据当事务1执行业务SQL前会先获取全局锁TC就会进行记录此时事务1释放DB锁去等待TC的通知删除快照或根据快照修复数据事务2拿到了DB锁开始执行业务SQL当事务2尝试获取全局锁时就会发现获取不到因为全局锁现在被事务1所持有此时假设恰好TC告知事务1进行数据回滚事务1则会重新获取DB锁但是DB锁此时被事务2所持有这样就形成了死锁怎么办事务2在尝试获取一段时间全局锁后一直拿不到就会放弃获取全局锁此时事务1就拿到了DB锁进行快照修复即可。

前提是两个事务均是由seata控制的事务才会这样。

假设事务2不是由seata控制的事务将会是怎样的

我们上面说过事务1记录undo_log时会记录数据修改前后的值当我们进行数据恢复时发现money此时为80此时需要我们进行报警处理人工的根据undo_log当中的数据进行数据恢复。

AT模式的优点一阶段完成直接提交事务释放数据库资源性能比较好利用全局锁实现读写隔离没有代码侵入框架自动完成回滚和提交

AT模式的缺点两阶段之间属于软状态属于最终一致框架的快照功能会影响性能但比XA模式要好很多3、TCC模式

TCC模式与AT模式非常相似每阶段都是独立事务区别在于TCC是通过人工代码控制来实现数据恢复需要实现三个方法

Confirm完成资源操作业务要求

Cancel预留资源释放可以理解为try的反向操作。

举例一个扣减用户余额的业务。

假设账户A原来余额是100需要余额扣减30元。

阶段一

阶段二Confirm)假如要提交Confirm则冻结金额扣减30

确认可以提交不过之前可用金额已经扣减过了这里只要清除冻结金额就好了

此时总金额

阶段二(Canncel)如果要回滚Cancel则冻结金额扣减30可用余额增加30需要回滚那么就要释放冻结金额恢复可用金额

TCC模型

可以看到TCC模式和AT模式极其相似但是区别在于AT模式采用全局锁undo_log的方式进行事务提交和回滚这里我们不再使用锁而是使用try-confirm-cancel的方式对操作进行记录。

当TC通知分支事务可以提交的时候分支事务直接执行confirm方法即可通知回滚时则执行cancel方法

Try资源检查和预留Confirm业务执行和提交Cancel预留资源的释放TCC的优点是什么

有代码侵入需要人为编写try、Confirm和Cancel接口太麻烦

事务悬挂对于已经空回滚的业务之前被阻塞的try操作恢复继续执行try就永远不可能confirm或cancel

执行try操作时应当判断cancel是否已经执行过了如果已经执行应当阻止空回滚后的try操作避免悬挂

空回滚当某分支事务的try阶段阻塞时可能导致全局事务超时而触发二阶段的cancel操作。

在未执行try操作时先执行了cancel操作这时cancel不能做回滚就是空回滚。

执行cancel操作时应当判断try是否已经执行如果尚未执行则应该空回

3、SAGA模式

模式下分布式事务内有多个参与者每一个参与者都是一个冲正补偿服务需要用户根据业务场景实现其正向操作和逆向回滚操作。

分布式事务执行过程中依次执行各参与者的正向操作如果所有正向操作均执行成功那么分布式事务提交。

如果任何一个正向操作执行失败那么分布式事务会去退回去执行前面各参与者的逆向回滚操作回滚已提交的参与者使分布式事务回到初始状态。

Saga也分为两个阶段

分布式事务和传统形式的事务区别有什么众所周知我们采用微服务框架开发项目时不同服务之间通过相互调用的方式完成业务处理用以下案例来描述分布式业务存在的问题

假设我们此时现在有一个系统其中包括下单系统、用户系统、仓库系统。

当我们进行下单时就需要创建订单信息同时需要对用户的余额进行扣减还需要对仓储系统的商品数量进行减少由于每个系统分别负责一部分的业务且其拥有独立的数据库信息因此我们就会有三个事务订单创建、余额扣减、商品剩余量扣减。

Seata配置

下载Seata服务端压缩包https://github.com/seata/seata/releases

4.1.2、修改conf目录中

DruidDataSource(druid)/BasicDataSource(dbcp)/HikariDataSource(hikari)

etc.datasource

mysql/oracle/postgresql/h2/oceanbase

etc.dbType

jdbc:mysql://localhost:3306/seata?useUnicodetrueallowPublicKeyRetrievaltruecharacterEncodingutf-8useSSLfalseserverTimezoneGMT%2b8##

数据库账号user

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

seata-server

由于我们使用了db模式存储事务日志所以我们需要创建一个seata数据库Seata数据库表初始化脚本

--------------------------------

The

--------------------------------

the

VARCHAR(32),transaction_service_group

VARCHAR(128),timeout

xmlnshttp://maven.apache.org/POM/4.0.0

xmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexsi:schemaLocationhttp://maven.apache.org/POM/4.0.0

http://maven.apache.org/xsd/maven-4.0.0.xsdmodelVersion4.0.0/modelVersiongroupIdcom.my.springcloud/groupIdartifactIdcloud-seata/artifactIdversion1.0-SNAPSHOT/versionpackagingpom/packagingmodulesmoduleseata-account-service/modulemoduleseata-order-service/modulemoduleseata-storage-service/modulemodulecloud-eureka-server7001/modulemodulecloud-eureka-server7002/modulemodulecloud-gateway-gateway/module/modules!--

统一管理jar包版本

--propertiesproject.build.sourceEncodingUTF-8/project.build.sourceEncodingmaven.compiler.source1.8/maven.compiler.sourcemaven.compiler.target1.8/maven.compiler.targetjunit.version4.12/junit.versionlog4j.version1.2.17/log4j.versionlombok.version1.16.18/lombok.versionmysql.version8.0.28/mysql.versiondruid.version1.2.4/druid.versionmybatis.spring.boot.version2.0.0/mybatis.spring.boot.version/properties!--

子模块继承之后,提供作用锁定版本子modlue不用写groupId和version

--dependencyManagementdependencies!--spring

boot

2.3.2--dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-dependencies/artifactIdversion2.3.2.RELEASE/versiontypepom/typescopeimport/scope/dependency!--spring

cloud

Hoxton.SR9--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-dependencies/artifactIdversionHoxton.SR9/versiontypepom/typescopeimport/scope/dependency!--spring

cloud

2.2.5.RELEASE--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-alibaba-dependencies/artifactIdversion2.2.5.RELEASE/versiontypepom/typescopeimport/scope/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactIdversion${mybatis.spring.boot.version}/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactIdversion${mysql.version}/version/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactIdversion${druid.version}/version/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdversion${lombok.version}/versionoptionaltrue/optional/dependencydependencygroupIdlog4j/groupIdartifactIdlog4j/artifactIdversion${log4j.version}/version/dependencydependencygroupIdjunit/groupIdartifactIdjunit/artifactIdversion${junit.version}/version/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdversion2021.1/versionexclusions!--版本较低1.3.0因此排除--exclusionartifactIdseata-spring-boot-starter/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency/dependencies/dependencyManagementbuildpluginsplugingroupIdorg.springframework.boot/groupIdartifactIdspring-boot-maven-plugin/artifactIdconfigurationaddResourcestrue/addResources/configuration/plugin/plugins/build

/project

dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusionsexclusionartifactIdseata-all/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency!--feign--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies2.3.3seata事务用到的表

DROP

enableenableClientBatchSendRequest

true#thread

NettyServerNIOWorkerserverExecutorThread-prefix

NettyServerBizHandlershareBossWorker

falseclientSelectorThreadPrefix

NettyClientSelectorclientSelectorThreadSize

netty

{#这里注意,等号前后都是配置,前面是yml里配置的事务组,后面是register.conf里定义的seata-servervgroupMapping.my_test_tx_group

seata-server#only

addressesseata_tc_server.grouplist

current

30retryPolicyBranchRollbackOnConflict

false}tm

、eureka、redis、zk、consul、etcd3、sofa##

注册中心为eurekatype

RandomLoadBalanceloadBalanceVirtualNodes

10nacos

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/application

seata-serverweight

http://192.168.1.204:8801namespace

applicationapolloAccesskeySecret

}zk

seata-account-servicedatasource:type:

com.alibaba.druid.pool.DruidDataSource

mysql驱动包url:

jdbc:mysql://localhost:3306/seata_account?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8

数据库名称username:

${spring.application.name}tx-service-group:

seata-serverenable-auto-data-source-proxy:

trueservice:default:

127.0.0.1:8091vgroup-mapping:seata-server:

defaultconfig:type:

所有Entity别名类所在包typeAliasesPackage:

配置mapper的扫描找到所有的mapper.xml映射文件mapperLocations:

configLocation:

classpath:mybatis/mybatis-config.xml#

eureka客户端配置

eureka:client:#表示是否向Eureka注册中心注册自己register-with-eureka:

truefetch-registry:

false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务service-url:#defaultZone:

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/defaultZone:

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/instance:#向注册中心注册服务IDinstance-id:

${spring.cloud.client.ip-address}:${server.port}prefer-ip-address:

true

Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)lease-renewal-interval-in-seconds:

30#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒)超时将剔除服务lease-expiration-duration-in-seconds:

import

com.alibaba.druid.pool.DruidDataSource;

import

io.seata.rm.datasource.DataSourceProxy;

import

org.apache.ibatis.session.SqlSessionFactory;

import

org.mybatis.spring.SqlSessionFactoryBean;

import

org.mybatis.spring.transaction.SpringManagedTransactionFactory;

import

org.springframework.beans.factory.annotation.Value;

import

org.springframework.boot.context.properties.ConfigurationProperties;

import

org.springframework.context.annotation.Bean;

import

org.springframework.context.annotation.Configuration;

import

org.springframework.core.io.support.PathMatchingResourcePatternResolver;import

使用Seata对数据源进行代理*/

{//加载数据源BeanConfigurationProperties(prefix

DataSource

DruidDataSource();}Value(${mybatis.mapperLocations})private

String

DataSourceProxy(dataSource);}Beanpublic

SqlSessionFactory

sqlSessionFactoryBean(DataSource

dataSourceProxy)

SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new

PathMatchingResourcePatternResolver().getResources(mapperLocations));sqlSessionFactoryBean.setTransactionFactory(new

SpringManagedTransactionFactory());return

sqlSessionFactoryBean.getObject();}}2.3.7主启动类去掉默认自动加载数据源

import

org.springframework.boot.SpringApplication;

import

org.springframework.boot.autoconfigure.SpringBootApplication;

import

org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;

import

org.springframework.cloud.netflix.eureka.EnableEurekaClient;

import

org.springframework.cloud.openfeign.EnableFeignClients;EnableEurekaClient

DataSourceAutoConfiguration.class)

public

{SpringApplication.run(SeataAccountApp.class,

args);}

http://mybatis.org/dtd/mybatis-3-mapper.dtd

mapper

namespacecom.my.springcloud.dao.AccountDaoresultMap

idBaseResultMap

typecom.my.springcloud.domain.Accountid

columnid

jdbcTypeDECIMAL//resultMapupdate

iddecreaseUPDATE

扣减账户余额*/RequestMapping(/account/decrease)public

CommonResult

{accountService.decrease(userId,

money);return

dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusionsexclusionartifactIdseata-all/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency!--feign--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency/dependencies2.4.3seata事务用到的表

DROP

enableenableClientBatchSendRequest

true#thread

NettyServerNIOWorkerserverExecutorThread-prefix

NettyServerBizHandlershareBossWorker

falseclientSelectorThreadPrefix

NettyClientSelectorclientSelectorThreadSize

netty

{#这里注意,等号前后都是配置,前面是yml里配置的事务组,后面是register.conf里定义的seata-servervgroupMapping.my_test_tx_group

seata-server#only

addressesseata_tc_server.grouplist

current

30retryPolicyBranchRollbackOnConflict

false}tm

、eureka、redis、zk、consul、etcd3、sofa##

注册中心为eurekatype

RandomLoadBalanceloadBalanceVirtualNodes

10nacos

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/application

seata-serverweight

http://192.168.1.204:8801namespace

applicationapolloAccesskeySecret

}zk

seata-storage-service#----------------------------数据源----------------------------datasource:type:

com.alibaba.druid.pool.DruidDataSourcedriverClassName:

jdbc:mysql://localhost:3306/seata_storage?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8username:

rootpassword:

truemax-pool-prepared-statement-per-connection-size:

20max-wait:

60000time-between-eviction-runs-millis:

60000min-evictable-idle-time-millis:

30000filters:

true#----------------------------seata----------------------------

seata:enabled:

${spring.application.name}tx-service-group:

seata-serverenable-auto-data-source-proxy:

trueservice:default:

127.0.0.1:8091vgroup-mapping:seata-server:

defaultconfig:type:

eureka:client:#表示是否向Eureka注册中心注册自己register-with-eureka:

truefetch-registry:

false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务service-url:#defaultZone:

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/defaultZone:

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/instance:#向注册中心注册服务IDinstance-id:

${spring.cloud.client.ip-address}:${server.port}prefer-ip-address:

true

Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)lease-renewal-interval-in-seconds:

30#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒)超时将剔除服务lease-expiration-duration-in-seconds:

90#MyBatis

mybatis:#所有Entity别名类所在包,多个路径用逗号分割typeAliasesPackage:

配置mapper的扫描找到所有的mapper,多个目录用逗号或者分号分隔mapperLocations:

configLocation:

classpath:mybatis/mybatis-config.xml

2.4.6数据源交给seata去代理

com.alibaba.druid.pool.DruidDataSource;

import

io.seata.rm.datasource.DataSourceProxy;

import

org.apache.ibatis.session.SqlSessionFactory;

import

org.mybatis.spring.SqlSessionFactoryBean;

import

org.mybatis.spring.transaction.SpringManagedTransactionFactory;

import

org.springframework.beans.factory.annotation.Value;

import

org.springframework.boot.context.properties.ConfigurationProperties;

import

org.springframework.context.annotation.Bean;

import

org.springframework.context.annotation.Configuration;

import

org.springframework.core.io.support.PathMatchingResourcePatternResolver;import

使用Seata对数据源进行代理*/

{//加载数据源BeanConfigurationProperties(prefix

DataSource

DruidDataSource();}Value(${mybatis.mapperLocations})private

String

DataSourceProxy(dataSource);}Beanpublic

SqlSessionFactory

sqlSessionFactoryBean(DataSource

dataSourceProxy)

SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new

PathMatchingResourcePatternResolver().getResources(mapperLocations));sqlSessionFactoryBean.setTransactionFactory(new

SpringManagedTransactionFactory());return

sqlSessionFactoryBean.getObject();}}2.4.7主启动类去掉默认自动加载数据源

EnableEurekaClient

DataSourceAutoConfiguration.class)

public

{SpringApplication.run(SeataStorageApp.class,

args);}

http://mybatis.org/dtd/mybatis-3-mapper.dtd

mapper

namespacecom.my.springcloud.dao.StorageDaoresultMap

idBaseResultMap

typecom.my.springcloud.domain.Storageid

columnid

jdbcTypeINTEGER//resultMapupdate

used

扣减库存*/RequestMapping(/storage/decrease)public

CommonResult

{storageService.decrease(productId,

count);return

dependenciesdependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-netflix-eureka-client/artifactId/dependency!--seata依赖--dependencygroupIdcom.alibaba.cloud/groupIdartifactIdspring-cloud-starter-alibaba-seata/artifactIdexclusionsexclusionartifactIdseata-all/artifactIdgroupIdio.seata/groupId/exclusion/exclusions/dependencydependencygroupIdio.seata/groupIdartifactIdseata-spring-boot-starter/artifactIdversion1.4.1/version/dependency!--feign--dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-openfeign/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactId/dependencydependencygroupIdorg.mybatis.spring.boot/groupIdartifactIdmybatis-spring-boot-starter/artifactId/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdcom.alibaba/groupIdartifactIddruid-spring-boot-starter/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactIdoptionaltrue/optional/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency!--

httpclient

--dependencygroupIdio.github.openfeign/groupIdartifactIdfeign-httpclient/artifactId/dependencydependencygroupIdio.github.openfeign/groupIdartifactIdfeign-okhttp/artifactId/dependency/dependencies2.5.3seata事务用到的表

DROP

enableenableClientBatchSendRequest

true#thread

NettyServerNIOWorkerserverExecutorThread-prefix

NettyServerBizHandlershareBossWorker

falseclientSelectorThreadPrefix

NettyClientSelectorclientSelectorThreadSize

netty

{#这里注意,等号前后都是配置,前面是yml里配置的事务组,后面是register.conf里定义的seata-servervgroupMapping.my_test_tx_group

seata-server#only

addressesseata_tc_server.grouplist

current

30retryPolicyBranchRollbackOnConflict

false}tm

、eureka、redis、zk、consul、etcd3、sofa##

注册中心为eurekatype

RandomLoadBalanceloadBalanceVirtualNodes

10nacos

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/application

seata-serverweight

http://192.168.1.204:8801namespace

applicationapolloAccesskeySecret

}zk

seata-order-service#----------------------------数据源----------------------------datasource:type:

com.alibaba.druid.pool.DruidDataSourcedriverClassName:

jdbc:mysql://localhost:3306/seata_order?useUnicodetruecharacterEncodingutf8zeroDateTimeBehaviorconvertToNulluseSSLtrueserverTimezoneGMT%2B8username:

rootpassword:

truemax-pool-prepared-statement-per-connection-size:

20max-wait:

60000time-between-eviction-runs-millis:

60000min-evictable-idle-time-millis:

30000filters:

true#----------------------------seata----------------------------

seata:enabled:

${spring.application.name}tx-service-group:

seata-serverenable-auto-data-source-proxy:

trueservice:default:

127.0.0.1:8091vgroup-mapping:seata-server:

defaultconfig:type:

eureka:client:#表示是否向Eureka注册中心注册自己register-with-eureka:

truefetch-registry:

false表示自己就是注册中心,我的职责就是维护服务实例,并不需要去检索服务service-url:#defaultZone:

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/defaultZone:

http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/instance:#向注册中心注册服务IDinstance-id:

${spring.cloud.client.ip-address}:${server.port}prefer-ip-address:

true

Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)lease-renewal-interval-in-seconds:

30#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒)超时将剔除服务lease-expiration-duration-in-seconds:

90#MyBatis

mybatis:#所有Entity别名类所在包,多个路径用逗号分割typeAliasesPackage:

配置mapper的扫描找到所有的mapper,多个目录用逗号或者分号分隔mapperLocations:

configLocation:

classpath:mybatis/mybatis-config.xml#

feign超时设置

日志级别BASIC就是基本的请求和响应信息httpclient:enabled:

true

开启feign对HttpClient的支持max-connections:

200

最大的连接数max-connections-per-route:

每个路径的最大连接数logging:level:io:seata:

import

com.alibaba.druid.pool.DruidDataSource;

import

io.seata.rm.datasource.DataSourceProxy;

import

org.apache.ibatis.session.SqlSessionFactory;

import

org.mybatis.spring.SqlSessionFactoryBean;

import

org.mybatis.spring.transaction.SpringManagedTransactionFactory;

import

org.springframework.beans.factory.annotation.Value;

import

org.springframework.boot.context.properties.ConfigurationProperties;

import

org.springframework.context.annotation.Bean;

import

org.springframework.context.annotation.Configuration;

import

org.springframework.core.io.support.PathMatchingResourcePatternResolver;import

使用Seata对数据源进行代理*/

{//加载数据源BeanConfigurationProperties(prefix

DataSource

DruidDataSource();}Value(${mybatis.mapperLocations})private

String

DataSourceProxy(dataSource);}Beanpublic

SqlSessionFactory

sqlSessionFactoryBean(DataSource

dataSourceProxy)

SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new

PathMatchingResourcePatternResolver().getResources(mapperLocations));sqlSessionFactoryBean.setTransactionFactory(new

SpringManagedTransactionFactory());return

sqlSessionFactoryBean.getObject();}}2.5.7主启动类去掉默认自动加载数据源

EnableFeignClients

DataSourceAutoConfiguration.class)//取消数据源的自动创建

public

{SpringApplication.run(SeataOrderApp.class,

args);}

service实现类添加GlobalTransactional

Service

创建订单-调用库存服务扣减库存-调用账户服务扣减账户余额-修改订单状态*

简单说下订单-扣库存-减余额-改状态*/OverrideGlobalTransactional(

rollbackFor

扣减库存log.info(-----订单微服务开始调用库存做扣减Count);storageService.decrease(order.getProductId(),

order.getCount());log.info(-----订单微服务开始调用库存做扣减end);//3

扣减账户log.info(-----订单微服务开始调用账户做扣减Money);accountService.decrease(order.getUserId(),

order.getMoney());log.info(-----订单微服务开始调用账户做扣减end);//4

修改订单状态从零到1,1代表已经完成log.info(-----修改订单状态开始);orderDao.update(order.getUserId(),

0);log.info(-----修改订单状态结束);log.info(-----下订单结束了O(∩_∩)O哈哈~);}

}mapper.xml

http://mybatis.org/dtd/mybatis-3-mapper.dtd

mapper

namespacecom.my.springcloud.dao.OrderDaoresultMap

idBaseResultMap

typecom.my.springcloud.domain.Orderid

columnid

jdbcTypeINTEGER//resultMapinsert

idcreateinsert

decrease(RequestParam(productId)

Long

orderService;GetMapping(/order/create)public

CommonResult

{orderService.create(order);return

new

http://localhost:2001/order/create

业务流程

添加GlobalTransactional注解开启seata事务

获得全局事务状态

GlobalTransactionContext.reload(xid);

GlobalStatus



SEO优化服务概述

作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。

百度官方合作伙伴 白帽SEO技术 数据驱动优化 效果长期稳定

SEO优化核心服务

网站技术SEO

  • 网站结构优化 - 提升网站爬虫可访问性
  • 页面速度优化 - 缩短加载时间,提高用户体验
  • 移动端适配 - 确保移动设备友好性
  • HTTPS安全协议 - 提升网站安全性与信任度
  • 结构化数据标记 - 增强搜索结果显示效果

内容优化服务

  • 关键词研究与布局 - 精准定位目标关键词
  • 高质量内容创作 - 原创、专业、有价值的内容
  • Meta标签优化 - 提升点击率和相关性
  • 内容更新策略 - 保持网站内容新鲜度
  • 多媒体内容优化 - 图片、视频SEO优化

外链建设策略

  • 高质量外链获取 - 权威网站链接建设
  • 品牌提及监控 - 追踪品牌在线曝光
  • 行业目录提交 - 提升网站基础权威
  • 社交媒体整合 - 增强内容传播力
  • 链接质量分析 - 避免低质量链接风险

SEO服务方案对比

服务项目 基础套餐 标准套餐 高级定制
关键词优化数量 10-20个核心词 30-50个核心词+长尾词 80-150个全方位覆盖
内容优化 基础页面优化 全站内容优化+每月5篇原创 个性化内容策略+每月15篇原创
技术SEO 基本技术检查 全面技术优化+移动适配 深度技术重构+性能优化
外链建设 每月5-10条 每月20-30条高质量外链 每月50+条多渠道外链
数据报告 月度基础报告 双周详细报告+分析 每周深度报告+策略调整
效果保障 3-6个月见效 2-4个月见效 1-3个月快速见效

SEO优化实施流程

我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:

1

网站诊断分析

全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。

2

关键词策略制定

基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。

3

技术优化实施

解决网站技术问题,优化网站结构,提升页面速度和移动端体验。

4

内容优化建设

创作高质量原创内容,优化现有页面,建立内容更新机制。

5

外链建设推广

获取高质量外部链接,建立品牌在线影响力,提升网站权威度。

6

数据监控调整

持续监控排名、流量和转化数据,根据效果调整优化策略。

SEO优化常见问题

SEO优化一般需要多长时间才能看到效果?
SEO是一个渐进的过程,通常需要3-6个月才能看到明显效果。具体时间取决于网站现状、竞争程度和优化强度。我们的标准套餐一般在2-4个月内开始显现效果,高级定制方案可能在1-3个月内就能看到初步成果。
你们使用白帽SEO技术还是黑帽技术?
我们始终坚持使用白帽SEO技术,遵循搜索引擎的官方指南。我们的优化策略注重长期效果和可持续性,绝不使用任何可能导致网站被惩罚的违规手段。作为百度官方合作伙伴,我们承诺提供安全、合规的SEO服务。
SEO优化后效果能持续多久?
通过我们的白帽SEO策略获得的排名和流量具有长期稳定性。一旦网站达到理想排名,只需适当的维护和更新,效果可以持续数年。我们提供优化后维护服务,确保您的网站长期保持竞争优势。
你们提供SEO优化效果保障吗?
我们提供基于数据的SEO效果承诺。根据服务套餐不同,我们承诺在约定时间内将核心关键词优化到指定排名位置,或实现约定的自然流量增长目标。所有承诺都会在服务合同中明确约定,并提供详细的KPI衡量标准。

SEO优化效果数据

基于我们服务的客户数据统计,平均优化效果如下:

+85%
自然搜索流量提升
+120%
关键词排名数量
+60%
网站转化率提升
3-6月
平均见效周期

行业案例 - 制造业

  • 优化前:日均自然流量120,核心词无排名
  • 优化6个月后:日均自然流量950,15个核心词首页排名
  • 效果提升:流量增长692%,询盘量增加320%

行业案例 - 电商

  • 优化前:月均自然订单50单,转化率1.2%
  • 优化4个月后:月均自然订单210单,转化率2.8%
  • 效果提升:订单增长320%,转化率提升133%

行业案例 - 教育

  • 优化前:月均咨询量35个,主要依赖付费广告
  • 优化5个月后:月均咨询量180个,自然流量占比65%
  • 效果提升:咨询量增长414%,营销成本降低57%

为什么选择我们的SEO服务

专业团队

  • 10年以上SEO经验专家带队
  • 百度、Google认证工程师
  • 内容创作、技术开发、数据分析多领域团队
  • 持续培训保持技术领先

数据驱动

  • 自主研发SEO分析工具
  • 实时排名监控系统
  • 竞争对手深度分析
  • 效果可视化报告

透明合作

  • 清晰的服务内容和价格
  • 定期进展汇报和沟通
  • 效果数据实时可查
  • 灵活的合同条款

我们的SEO服务理念

我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。

提交需求或反馈

Demand feedback