持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情
一、微服务发展
1.1 微服务架构
1.1.1 springcloud全家桶
一般是eureka为注册中心,feign+ribbon作为RPC调用,zuul或gateway作为网关,hystrix作为服务降级,用zipkin和sleuth作为链路监控,config作为配置中心,stream做消息中间件集成,还有springSecurity配合做安全认证.
1.1.2 dubbo
当然还有部分中小公司使用dubbo+zookeeper.
1.1.3 大厂自研组件
很多大厂都是自研组件,部分大厂以dubbo为核心自研组件.
1.1.4 springcloud alibaba
阿里把自己的微服务技术融入进springcloud体系和标准,nacos、dubbo、seata(分布式事务)、sentinal(限流降级)、rocketmq. 另外再加上携程开源的配置中心apollo、大众点评开源的链路监控(CAT)
因为他维护活跃、又是中文文档、中文社区.未来可能是国内微服务框架的主流
二、注册中心选型
2.1 注册中心对比
2.1.1 eureka
AP模型,设计之初就是想保证可用性.各个server之间是相互独立的,不存在leader.只要有一个leader存活就还能提供注册.
2.1.2 zookeeper
典型的CP,牺牲可用性保障数据一致性.当他的master挂了之后会停止服务,直到选出新的leader.
2.1.3 consul
基于raft算法的CP模型
2.1.4 nacos
基于raft算法的CP模型,也可以支持配置成AP,功能最强大,包括雪崩保护、自动注销实例、监听支持、多数据中心.
2.2 nacos部署
详细官方文档:nacos.io/zh-cn/docs/…
在0.7版本之前,在单机模式时nacos使用嵌入式数据库实现数据的存储,不方便观察数据存储的基本情况。0.7版本增加了支持mysql数据源能力,具体的操作步骤:
- 安装数据库,版本要求:5.6.5+
- 初始化mysql数据库,数据库初始化文件:nacos-mysql.sql
- 修改conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos_devtest
db.password=youdontknow
2.2.1 单机版部署
- 只需要解压开之后,到bin目录下执行:
sh startup.sh -m standalone
账户:nacos 密码:nacos
常见问题:
访问http://localhost:8848/nacos/v1/ns/service/list 提示server is DOWN now, please try again later!
删除掉nacos/data目录重新启动
2.2.2 多环境隔离
-
在nacos上创建一个命名空间,如dev,id也填dev
-
在properties配置里增加这行:
spring.cloud.nacos.discovery.namespace=dev
三、分布式事务选型
除了阿里的Seata之外,目前还没有特别成熟的框架.像ByteTcc、LCN虽然还不错,但是毕竟只是少数人用,如果要拿到生产上去使用,必须要确保自己能吃透里面的源码,以保证出了bug自己能够修改.
Seata支持的分布式方案:Tcc、XA、AT、Saga
AT:是通过记录sql执行的日志,通过做反向日志来进行回滚的方案,接口层面就不用关心数据回滚了.
Saga: 长事务,多个事务串联在一起
3.1 安装Seata
下载地址: github.com/seata/seata…
修改启动脚本,主要是改小配置,电脑内存够也可以不改.
启动命令:
sh seata-server.sh -p 8091 -h 127.0.0.1 -m file
3.2 Seata+Nacos+SpringCloudAlibaba部署指南
我使用的版本:
SpringCloudAlibaba : 2.1.1.RELEASE
Nacos : 1.1.4
Seata : 0.9
版本非常重要,有时版本不对,项目启动会报一些莫名其妙的错误.
3.2.1 安装Nacos
解压之后,如果是单机部署的话,可以点击修改startup.sh中的MODE为standalone.
export SERVER="nacos-server"
# 修改MODE
export MODE="standalone"
export FUNCTION_MODE="all"
==注意如果电脑ip变化了,需要删除/nacos/data文件夹,然后在重启.否则会提示服务down==
启动命令
startup.sh
3.2.2 安装seata
- 下载地址:github.com/seata/seata…
- 解压seata文件夹
- 修改seata/conf/file.conf文件
改动点:
- 修改自定义事务名称,server 中 vgroup_mapping.my_test_tx_group 的名称,随意定义
- 修改事务日志存储模式为db。(默认为文件)store中的mode
- 修改数据库信息
transport {
# tcp udt unix-domain-socket
type = "TCP"
#NIO NATIVE
server = "NIO"
#enable heartbeat
heartbeat = true
#thread factory for netty
thread-factory {
boss-thread-prefix = "NettyBoss"
worker-thread-prefix = "NettyServerNIOWorker"
server-executor-thread-prefix = "NettyServerBizHandler"
share-boss-worker = false
client-selector-thread-prefix = "NettyClientSelector"
client-selector-thread-size = 1
client-worker-thread-prefix = "NettyClientWorkerThread"
# netty boss thread size,will not be used for UDT
boss-thread-size = 1
#auto default pin or 8
worker-thread-size = 8
}
shutdown {
# when destroy server, wait seconds
wait = 3
}
serialization = "seata"
compressor = "none"
}
service {
#vgroup->rgroup
# 1.自定义事务组名称
vgroup_mapping.my_test_tx_group = "xiangjiao_tx_group"
#only support single node
default.grouplist = "127.0.0.1:8091"
#degrade current not support
enableDegrade = false
#disable
disable = false
#unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
max.commit.retry.timeout = "-1"
max.rollback.retry.timeout = "-1"
}
client {
async.commit.buffer.limit = 10000
lock {
retry.internal = 10
retry.times = 30
}
report.retry.count = 5
tm.commit.retry.count = 1
tm.rollback.retry.count = 1
}
## transaction log store
store {
## store mode: file、db
# 2.修改为db
mode = "db"
## file store
file {
dir = "sessionStore"
# branch session size , if exceeded first try compress lockkey, still exceeded throws exceptions
max-branch-session-size = 16384
# globe session size , if exceeded throws exceptions
max-global-session-size = 512
# file buffer size , if exceeded allocate new buffer
file-write-buffer-cache-size = 16384
# when recover batch read size
session.reload.read_size = 100
# async, sync
flush-disk-mode = async
}
## database store
db {
## the implement of javax.sql.DataSource, such as DruidDataSource(druid)/BasicDataSource(dbcp) etc.
datasource = "dbcp"
## mysql/oracle/h2/oceanbase etc.
db-type = "mysql"
driver-class-name = "com.mysql.jdbc.Driver"
url = "jdbc:mysql://127.0.0.1:3306/seata"
# 3.修改数据库信息
user = "root"
password = "root"
min-conn = 1
max-conn = 3
global.table = "global_table"
branch.table = "branch_table"
lock-table = "lock_table"
query-limit = 100
}
}
lock {
## the lock store mode: local、remote
mode = "remote"
local {
## store locks in user's database
}
remote {
## store locks in the seata's server
}
}
recovery {
#schedule committing retry period in milliseconds
committing-retry-period = 1000
#schedule asyn committing retry period in milliseconds
asyn-committing-retry-period = 1000
#schedule rollbacking retry period in milliseconds
rollbacking-retry-period = 1000
#schedule timeout retry period in milliseconds
timeout-retry-period = 1000
}
transaction {
undo.data.validation = true
undo.log.serialization = "jackson"
undo.log.save.days = 7
#schedule delete expired undo_log in milliseconds
undo.log.delete.period = 86400000
undo.log.table = "undo_log"
}
## metrics settings
metrics {
enabled = false
registry-type = "compact"
# multi exporters use comma divided
exporter-list = "prometheus"
exporter-prometheus-port = 9898
}
support {
## spring
spring {
# auto proxy the DataSource bean
datasource.autoproxy = false
}
}
- 创建数据库seata
新建一个数据库seata,并执行conf/db_store.sql文件,建立所需的表
另外还需要在你的每个业务数据库中执行conf/db_undo_log.sql 5. 修改conf/registry.conf配置文件
修改type为nacos
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
serverAddr = "localhost:8848"
namespace = ""
cluster = "default"
username="nacos"
password="nacos"
}
- 启动seata
seata-server.sh
启动完成后,可以登陆nacos,127.0.0.1/8848/nacos看看服务是否注册成功
==我出现过登陆时用户名密码不对的情况,后来重新配置了JDK环境变量解决了.==
- 接下来就是项目了,项目方面就不多描述了,直接看我的项目怎么配置就行了.
除了使用全局事务注解@GlobalTransactional(name = "createReport",rollbackFor = Exception.class)外,还需要配置数据源:
package com.mmc.reward.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.boot.autoconfigure.MybatisProperties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import javax.sql.DataSource;
import java.io.IOException;
/**
* Description:
* author: yu.hb
* Date: 2019-11-01
*/
@Configuration
@EnableConfigurationProperties({MybatisProperties.class})
public class DataSourceConfiguration {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource dataSource() {
return new DruidDataSource();
}
@Bean
public DataSourceProxy dataSourceProxy(DataSource dataSource) {
return new DataSourceProxy(dataSource);
}
@Bean
public SqlSessionFactoryBean sqlSessionFactoryBean(DataSourceProxy dataSourceProxy,
MybatisProperties mybatisProperties) {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSourceProxy);
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
try {
Resource[] mapperLocaltions = resolver.getResources(mybatisProperties.getMapperLocations()[0]);
bean.setMapperLocations(mapperLocaltions);
if (StringUtils.isNotBlank(mybatisProperties.getConfigLocation())) {
Resource[] resources = resolver.getResources(mybatisProperties.getConfigLocation());
bean.setConfigLocation(resources[0]);
}
} catch (IOException e) {
e.printStackTrace();
}
return bean;
}
}
==注意: 分布式事务分组名是对应的seata/conf/file.conf中的,3个地方都是配一样的,我这里配的是xiangjiao_tx_group==
vgroup_mapping.my_test_tx_group = "xiangjiao_tx_group"
对应项目中application.properties中的
spring.cloud.alibaba.seata.tx-service-group=xiangjiao_tx_group
对应项目中的file.conf文件中的
vgroup_mapping.xiangjiao_tx_group = "default"
四、熔断限流选型
Sentinel和Hystix对比
Sentinel的功能有流量控制、熔断降级、系统负载保护、监控等.
在熔断降级的设计上,Sentinel和Hystrix采取了完全不一样的方式.
Hystrix:
- 采用的上线程池隔离的方式,来对依赖进行了隔离.这样做的好处是资源与资源之间进行了彻底的隔离.缺点是增加了切换线程的成本.并且需要给资源提前分配线程池大小.
Sentinel:
- 通过线程并发数控制
线程数如果被堆积了,到一定数量,新请求就会被拒绝
- 通过响应时间对资源进行降级
当依赖的资源出现响应时间超时时,所有对该资源对访问都会被直接拒绝.
熔断策略有三种:
- 慢调用比例
- 异常比例
- 异常数
五、配置中心选型
常用的配置中心: SpringCloudConfig、Nacos、Apollo
Apollo比较重,适用于中大型公司.小公司来说Nacos就够用了,或者如果是使用的SpringCloud这一套,那么就使用SpringCloudConfig.
六、监控中心选型
2015-2016用的比较火的是Zabbix,2018-2019用的比较火的是Prometheus
Prometheus可以监控内存、cpu、中间件如Redis,并且可以进行报警.
监控机器资源、JVM进程、系统(QPS、延时、异常)
业务指标:异常、QPS、接口时延
七、接入日志中心
如果节点机器数多了,想找日志就非常麻烦,每台机器去找日志非常费时间.
知名一点的开源的日志中心较少,一般公司会自研日志中心.一般采用Es+Hbase来实现.
八、链路追踪选型
Sleuth、Zipkin、Cat、Skywalking
CAT:美团点评开源,CAT很大的优势是实时
九、API网关选型对比
Zuul、Nginx+Lua、Kong