cloud-provider-payment8001
: 支付服务
cloud-consumer-order80
: 消费者订单服务
已停更,日后不再推荐使用。
注意点:
C: Consistency 强一致性 A: Availability 可用性 P: Partition Tolerance 分区容错性 CAP理论关注粒度是数据,而不是整体系统设计的策略,一般来说系统只能满足三者之其二。 AP:Eureka CP:Zookeeper、Consul
组件名 | 语言 | CAP | 服务健康检查 | 对外暴露接口 | SpringCloud集成 |
---|---|---|---|---|---|
Eureka | Java | AP | 可配支持 | HTTP | 已集成 |
Consul | Go | CP | 支持 | HTTP/DNS | 已集成 |
Zookeeper | Java | CP | 支持 | 客户端 | 已集成 |
Spring Cloud Ribbon
是基于 Netflix Ribbon
实现的一套 客户端负载均衡的工具。
主要功能是提供 客户端的软件负载均衡算法和服务调用。Ribbon
客户端组件提供一系列完善的配置项如连接超时、重试等。简单来说就是在配置文件中列出 Load Balancer
后面所有的机器, Ribbon
会自动地帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们很容易使用Ribbon
实现自定义的负载均衡算法。
简单的说就是将用户的请求平摊地分配到多个服务上,从而达到系统的HA(High Availability),常见的负载均衡软件有Nginx、LVS,硬件有F5等。
Nginx是服务器负载均衡,客户端所有请求都会教给Nginx,然后由Nginx实现转发请求。
Ribbon是本地负载均衡,在调用微服务接口时,会在注册中心获取注册信息服务列表之后缓存到JVM本地,从而在本地实现RPC(远程过程调用)远程服务调用。
进程内LB: 将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
集中式LB: 即在服务的消费方与提供方之间使用独立的LB设施(可以是硬件如F5,软件如Nginx),由该设施负责把访问请求通过某种策略转发至服务的提供方。
package com.netflix.loadbalancer;
public interface IRule {
Server choose(Object var1);
void setLoadBalancer(ILoadBalancer var1);
ILoadBalancer getLoadBalancer();
}
算法名称 | 作用方式 |
---|---|
RoundRobinRule | 轮询 |
WeightedResponseTimeRule | 对轮询的扩展,响应速度越快的实例选择权重越大,越容易被选择。 |
RandomRule | 随机 |
RetryRule | 先按照轮询的策略获取服务,如果获取服务失败则在指定时间内会进行重试。 |
BestAvailableRule | 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务 |
AvailabilityFilteringRule | 先过滤掉故障实例,再选择并发较小的实例 |
ZoneAvoidanceRule | 默认规则,符合判断Server所在区域的性能和Server的可用性选择服务器。 |
SpringBootApplication
所在包同级包下新建包MySelfRule
,配置@Configuration、@Bean
等,返回需要的策略。不能与SpringBootApplication
主启动类同级包下是因为SpringBootApplication
是一个复合注解,包含了@ComponentScan
注解,而Ribbon
自定义策略如果在这个注解扫描下将会全局通用,失去了自制的目的。@RibbonClient(name = "需要定制的服务名称",configuration = 自定义策略类.class)
轮询:实际调用服务器位置下标=REST接口请求次数%服务集群总数量,每次服务重启后REST接口计数从1开始
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
log.warn("no load balancer");
return null;
} else {
Server server = null;
int count = 0;
while(true) {
if (server == null && count++ < 10) {
List<Server> reachableServers = lb.getReachableServers();
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();
if (upCount != 0 && serverCount != 0) {
int nextServerIndex = this.incrementAndGetModulo(serverCount);
server = (Server)allServers.get(nextServerIndex);
if (server == null) {
Thread.yield();
} else {
if (server.isAlive() && server.isReadyToServe()) {
return server;
}
server = null;
}
continue;
}
log.warn("No up servers available from load balancer: " + lb);
return null;
}
if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: " + lb);
}
return server;
}
}
}
private int incrementAndGetModulo(int modulo) {
int current;
int next;
do {
current = this.nextServerCyclicCounter.get();
next = (current + 1) % modulo;
} while(!this.nextServerCyclicCounter.compareAndSet(current, next));
return next;
}
Feign是一个声明式WebService客户端。使用Feign能让编写WebService变得更加简单。它的使用方式是定义一个服务接口然后在上面添加注解。Feign也支持可插拔式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持Spring MVC标准注解和HttpMessageConverters。Feign可与Eureka和Ribbon组合使用支持负载均衡。
Feign旨在使用JavaHttp客户端变得更加容易。
以往使用Ribbon+RestTemplate
,利用RestTemplate
对HTTP请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由于对服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以通常会针对每个微服务自行封装一些客户端类库来包装这些依赖服务的调用。所以Feign在此基础上做了进一步封装,来帮助我们定义和实现依赖服务接口的定义。在Feign的实现下,通过注解即可完成对服务提供方的接口绑定。并且集成了Ribbon
.
名称 | 简介 |
---|---|
Feign | SpringCloud组件中的一个轻量级RESTful的HTTP客户服务端,内置了Ribbon,用来做客户端负载均衡,去调用服务注册中心的服务。利用Feign的注解定义接口,调用这个接口,就可以调用服务注册中心的服务。 |
OpenFeign | 在Feign的基础上支持了Spring MVC的注解。使用@FeignClint 可以解析Spring MVC的@RequestMapping 下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 |
默认1s,超时报错,可通过 application.yml
修改
# 设置feign 客户端超时时间(openFeign默认支持ribbon)
ribbon:
# 指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
# 指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
创建配置类
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
修改配置文件 application.yml
logging:
level:
# feign日志以什么级别监控哪个接口
edu.dlut.springcloud.service.PaymentFeignService: debug
Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程池隔离、信号量隔离、熔断、降级回退。在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有很多不可控的因素,比如网络连接变慢,资源突然繁忙,暂时不可用,服务脱机等。
名称 | 描述 | 发生条件 |
---|---|---|
服务降级 | 服务器忙,请稍后再试,不让客户端等待立即返回一个友好提示,fallback | 程序运行异常、超时、服务熔断触发服务降级、线程池/信号量已满 |
服务熔断 | 类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级的方法并返回友好提示 | 服务的降级->进而熔断->恢复调用链路 |
服务限流 | 秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个。有序进行 |
# mac 通过 Homebrew 安装 JMeter
$ brew install jmeter
$ brew install jmeter --with-plugins # 可选
$ jmeter 启动GUI
# 线程组->Add->Sampler->HTTP Request
com.netflix.client.ClientException: Load balancer does not have available server for client
eureka:
client:
fetch-registry: false # 将 false 改为 true 默认为 true
当前服务不可用了,使用服务降级,调用兜底方案。既可以放在消费端,也可以放在服务端,但是一般放在消费端。
// 处理方法注解
@HystrixCommand(fallbackMethod = "备用处理的方法[需要自己手写]", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
// 主启动类注解
@EnableCircuitBreaker
# yaml 文件
feign:
hystrix:
enabled: true
// 主启动类
@EnableHystrix
// 方法配置使用 @HystrixCommand 注解
以上方法每个业务方法都存在一个兜底方法,代码冗余,要将统一的和自定义的进行分开隔离。
// 在方法上加 @HystrixCommand 注解
@HystrixCommand
public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
int a = 10 / 0;
return paymentHystrixService.paymentInfo_TimeOut(id);
}
// 在类上加 @DefaultProperties(defaultFallback = "paymentTimeoutFallbackMethod") 注解
// 需要自定义 fallback 方法
为 Feign
客户端定义的接口添加一个服务降级处理的实现类即可实现解耦。
可能要面对的异常:运行时异常,请求超时,服务器宕机。
// 实现类上加 @Component 注解
// 接口上加
@FeignClient(value = "微服务名称", fallback = 实现类名称.class)
熔断类型 | 描述 |
---|---|
熔断打开 | 请求不再调用当前服务,内部设置一般为MTTR(平均故障处理时间),当打开长达导所设时钟则进入半熔断状态 |
熔断关闭 | 熔断关闭后不会对服务进行熔断 |
熔断半开 | 部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断 |
Circuit Breaker - Martin Fowler
断路->自检->重试->恢复
// Service
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// 请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),// 时间窗口期/时间范文
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")// 失败率达到多少后跳闸
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
if (id < 0)
throw new IllegalArgumentException("*****id不能是负数");
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
return "id 不能负数,请稍后重试,o(╥﹏╥)o id:" + id;
}
// Controller
@GetMapping("/circuit/{id}")
@HystrixCommand
public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
String result = paymentService.paymentCircuitBreaker(id);
log.info("***result:" + result);
return result;
}
// 添加相关依赖
// 配置 yml
// 主启动类上添加注解
@EnableHystrixDashboard
// http://localhost:8001/hystrix.stream
// 在被监控的微服务的主启动类里添加
/**
* 此配置是为了服务监控而配置,与服务容错本身无观,springCloud 升级之后的坑
* ServletRegistrationBean因为springboot的默认路径不是/hystrix.stream
* 只要在自己的项目中配置上下面的servlet即可
*
* @return
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean<>(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
三大核心概念:路由,断言,过滤器。
yaml
配置式spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
uri: http://localhost:8001
# uri: lb://cloud-payment-service # 匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** # 断言 路径相匹配的进行路由
- id: payment_route2
uri: http://localhost:8001
# uri: lb://cloud-payment-service
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
@Configuration
public class Gateway {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
// 仍然是三个参数 "custom_path" 是id
// route -> route.path("/guonei") 是 Predicate
// uri("http://news.baidu.com/guonei") 是 uri
routes.route("custom_path",
route -> route.path("/guonei")
.uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}
# 添加
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: payment_route # 路由的id 没有规定规则但要求唯一,建议配合服务名
# uri: http://localhost:8001
uri: lb://cloud-payment-service # lb://serviceName 是SpringCloud提供的负载均衡
predicates:
- Path=/payment/get/** # 断言 路径相匹配的进行路由
使用方式 - Spring Cloud Gateway Predicate
使用方式 - Spring Cloud Gateway Filter
实现 GlobalFilter, Ordered
接口并重写 filter
方法
@Component
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("come in global filter: {}", new Date());
ServerHttpRequest request = exchange.getRequest();
String uname = request.getQueryParams().getFirst("uname");
if (uname == null) {
log.info("用户名为null,非法用户");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
// 放行
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
每一个微服务都带着一个自己的 application.yml
,如果项目里有几百个微服务配置文件会出现什么问题呢?
Spring Cloud Config 为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部支持。
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
skipSslValidation: true # 跳过ssl认证
uri: https://github.com/raymond-zhao/spring-cloud-config.git
search-paths:
- spring-cloud-config
label: master
// 主启动类
@EnableConfigServer
# bootstrap.yml
在客户端 3355 微服务中修改
<!-- 添加 actuator 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
// Controller 添加
@RefreshScope
做完上述步骤之后,客户端还是不会自动刷新,需要手动发起 POST
请求
$ curl -X POST "http://localhost:3355/actuator/refresh"
假如有多个微服务客户端 3355、3366、3377...每个服务都要执行一次 POST
请求吗?能不能采用 广播 的形式?达到一次通知,处处生效的目的?
但是如果实现了广播,那假如有100个微服务,只修改了一个配置文件,其它的99个也要接收通知吗?
在微服务架构的系统中,通常会使用 轻量级的消息代理 来构建一个 共用的消息主题,并让系统中所有的微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以称为消息总线。在总线上的各个实例,都可以方便地广播一些需要让其他连接在该主题上的实例都知道的消息。
ConfigClient
实例都监听MQ
中同一个Topic(Spring Cloud Bus)
。当一个服务刷新数据的时候,它会把这个信息放入到 Topic
中,这样其它监听同一Topic
的服务就能得到通知,然后去更新自身的配置。
RabbitMQ
和Kafka
/bus/refresh
,从而刷新所有客户端的配置。ConfigServer
的 /bus/refresh
端点,从而刷新所有客户端的配置。3344 的改动
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
# 暴露bus刷新配置的端点
management:
endpoints:
web:
exposure:
include: "bus-refresh"
一次请求,处处生效。
$ curl -X POST "http://localhost:3344/actuator/bus-refresh"
$ curl -X POST "http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}"
# /bus/refresh 请求不再发送到具体的服务实例上,而是发给 Config Server 并通过 destination 参数类指定需要更新配置的服务或实例
# destination 是指项目 yaml 配置文件中的 spring.application.name:server.port
# 只通知 3355
$ curl -X POST "http://localhost:3344/actuator/bus-refresh/config-client:3355"
Spring Cloud Stream Documentation
屏蔽底层消息中间件的差异,降低切换成本,统一消息的编程模型。
Spring Cloud Stream 是一个构建消息驱动微服务的框架。
inputs
或者 outputs
来与 Spring Cloud Stream 中binder
对象交互。binding
,而 Spring Cloud Stream 的binder
对象负责与消息中间件交互。Spring Integration
来连接消息代理中间件以实现消息事件驱动。RabbitMQ,Kafka
SubscribableChannel
,由MessageHandler
消息处理器所订阅Channel
通道,使得应用程序不需要再考虑各种不同的消息中间件实现组成 | 说明 |
---|---|
Middleware |
中间件,目前只支持RabbitMQ和Kafka |
Binder |
Binder是应用于消息中间件之间的封装,目前实行了Kafka和RabbitMQ的Binder,通过Binder可以很方便的连接中间件,可以动态的改变消息类型(对应于Kafka的topic,RabbitMQ的exchange),这些都可以通过配置文件来实现 |
@Input |
注解标识输入通道,通过该输入通道接收到的消息进入应用程序 |
@Output |
注解标识输出通道,发布的消息将通过该通道离开应用程序 |
@StreamListener |
监听队列,用于消费者的队列的消息接收 |
@EnableBinding |
指信道channel和exchange绑定在一起 |
cloud-stream-rabbitmq-provider8801
cloud-eureka-server7001
cloud-stream-rabbitmq-provider8801
cloud-stream-rabbitmq-consumer8802
cloud-eureka-server7001
cloud-stream-rabbitmq-provider8801
cloud-stream-rabbitmq-consumer8802
cloud-stream-rabbitmq-consumer8803
两个问题:重复消费,消息持久化。
设想一个场景,订单系统做集群部署,都会从RabbitMQ
中获取订单信息,加入一个订单被两个服务获取到,那么一个人购买了一个东西,但是却产生了两条购买记录,对买家来说是好事,但是对卖家来说...
group
是不同的,组流水号不一样,被认为不同组,可以消费。这时可以使用 Spring Cloud Stream
的消息分组来解决,在Stream
中处于同一个group
中的多个消费者是竞争关系,就能够保证消息只会被其中一个服务消费一次。
只需要在application.yml
中修改配置即可,即spring.cloud.stream.bindings.input.group
设置同一个名称。
如果消费者机器下线了,但是生产者在消费者下线期间又生产了消息,那消费者及其上线后会消费在下线期间产生的消息。
Spring Cloud Sleuth Documentation
在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的服务节点来协同产生最后的请求结果,每一个前端请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或者错误都会引起整个请求的失败。
<!--包含了sleuth+zipkin-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
cloud-eureka-server7001
cloud-eureka-server7002
cloud-provider-payment8001
cloud-consumer-order80
# java -jar zipkin-server...jar
# localhost:9411/zipkin
Spring Cloud Alibaba - Documentation
在mac或者其他类Unix系统上启动nacos时不会再出现 Nacos 的小图案了!!!
/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/bin/java -Xms512m -Xmx512m -Xmn256m -Dnacos.standalone=true -Djava.ext.dirs=/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/jre/lib/ext:/Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home/lib/ext -Xloggc:/Users/raymond/Downloads/nacos/logs/nacos_gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dloader.path=/Users/raymond/Downloads/nacos/plugins/health,/Users/raymond/Downloads/nacos/plugins/cmdb,/Users/raymond/Downloads/nacos/plugins/mysql -Dnacos.home=/Users/raymond/Downloads/nacos -jar /Users/raymond/Downloads/nacos/target/nacos-server.jar --spring.config.location=classpath:/,classpath:/config/,file:./,file:./config/,file:/Users/raymond/Downloads/nacos/conf/ --logging.config=/Users/raymond/Downloads/nacos/conf/nacos-logback.xml --server.max-http-header-size=524288
nacos is starting with standalone
nacos is starting,you can check the /Users/raymond/Downloads/nacos/logs/start.out
切记几种启动方式的区别,默认开启是集群模式,根据情况使用。
# localhost:8848/nacos
# 默认账号密码都是 nacos
$ sh startup.sh -m standalone
$ sh shutdown.sh
内置Ribbon
负载均衡,需要结合RestTemplate
使用,以及 @LoadBalanced
注解
cloudalibaba-provider-payment9001
cloudalibaba-provider-payment9002
cloudalibaba-consumer-nacos-order83
NACOS支持 AP 和 CP 的切换
cloudalibaba-config-nacos-client3377
新增 bootstrap.yml, application.yml
nacos
配置管理中添加的配置文件后缀名只能是yaml
,而不能是yml
.
# 配置文件名格式
${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
Namespace
默认是public
,Namespace
主要用来实现隔离,假如有三个环境:开发、测试、生产,那么可以创建三个Namespace
,不同的Namespace
之间是相互隔离的。
Group
默认是Default_Group
,Group
可以把不同的微服务划分到同一个分组
Service
是微服务,一个Service
可以包含多个Cluster
,Nacos Cluster
默认是Default
,是对指定微服务的一个虚拟化分。
Instance
是微服务的实例。
# spring.profiles.active 即是 Data Id
spring:
profiles:
active: dev # 开发环境
# active: test # 测试环境
# active: info # 开发环境
spring:
cloud:
nacos:
config:
group: DEV_GROUP
spring:
cloud:
nacos:
config:
namespace: 11586938-ae5d-4332-b41a-603a3f37420a
Nacos
默认自带的是嵌入式数据库derby
derby
到MySQL
切换配置步骤
nacos-server/nacos/conf
找到nacos-sql
脚本,到MySQL
数据库中执行。conf/application.properties
文件,增加支持MySQL
数据源配置(目前只支持MySQL
),添加MySQL
数据源的相关信息。重新启动Nacos
,可以看到是个全新的空记录界面。
连接MySQL
数据库通过nginx
监听端口号1111
,然后进行代理转发到集群的三台nacos
服务器上。
/nacos/conf
找到nacos-sql
脚本,到MySQL
数据库中执行,生成数据库。conf/application.properties
文件,增加支持MySQL
数据源配置(目前只支持MySQL
),添加MySQL
数据源的相关信息。spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://本机或服务器IP:3306/数据库名?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=填写自己的
db.password=填写自己的
conf/cluster.conf.example
到conf/cluster.conf
用作修改文件$ cp conf/cluster.conf.example conf/cluster.conf
conf/cluster.conf
添加集群主机及端口号,建议填写本机局域网ip
,而不要填127.0.0.1
,centOS
可通过hostname -i
查看,macOS
通过ifconfig en0
查看。$ vi cluster.conf
# It is ip
192.168.0.108:3333
192.168.0.108:4444
192.168.0.108:5555
bin/startup.sh
,增加 -p 端口号
启动方式,默认启动方式不可传入-p
参数$ vi startup.sh
# 进入 vim 之后按下 : 输入 set nu 显示行号 在差不多54行左右
# 在 57行 while getopts ":m:f:s:" 末尾添加 p: 表示端口的意思
# 添加 66、67 行
# 在134行左右处 ${JAVA} ${JAVA_OPT} 之间添加 -Dserver.port=${PORT} 表示接收端口参数
# :wq 保存退出
54 export SERVER="nacos-server"
55 export MODE="cluster"
56 export FUNCTION_MODE="all"
57 while getopts ":m:f:s:p:" opt
58 do
59 case $opt in
60 m)
61 MODE=$OPTARG;;
62 f)
63 FUNCTION_MODE=$OPTARG;;
64 s)
65 SERVER=$OPTARG;;
66 p)
67 PORT=$OPTARG;;
68 ?)
69 echo "Unknown parameter"
70 exit 1;;
71 esac
72 done
134 nohup $JAVA -Dserver.port=${PORT} ${JAVA_OPT} nacos.nacos >> ${BASE_DIR}/log s/start.out 2>&1 &
nginx
配置# $ yun install nginx # centOS
$ brew install nginx # mac
$ vi /usr/local/etc/nginx/nginx.conf
# 添加 upstream cluster
# 修改监听端口
# 修改 location
33 #gzip on;
34
35 upstream cluster {
36 server 127.0.0.1:3333;
37 server 127.0.0.1:4444;
38 server 127.0.0.1:5555;
39 }
40
41 server {
42 listen 1111;
43 server_name localhost;
44
45 #charset koi8-r;
46
47 #access_log logs/host.access.log main;
48
49 location / {
50 #root html;
51 #index index.html index.htm;
52 proxy_pass http://cluster;
53 }
54 }
nacos/bin
,启动并验证$ sh startup.sh -p 3333
$ sh startup.sh -p 4444
$ sh startup.sh -p 5555
$ ps -ef|grep nacos|grep -v grep|wc -l # 查看启动的nacos数量
$ cd /usr/local/Cellar/nginx/1.17.10/bin
$ ./nginx -c /usr/local/etc/nginx/nginx.conf
$ ps -ef | grep nginx # 查看 Nginx 启动情况
# 浏览器访问 localhost:1111/nacos/#/login
# 登录之后所进行的操作,比如添加配置项,启动微服务注册,将会被记录到 MySQL 数据库中。
Sentinel - Alibaba GitHub Wiki
Sentinel 分为两个部分:
下载jar
包 GitHub Releases,java - jar xxxx.jar
cloudalibaba-sentinel-service8401
java -jar sentinel-dashboard-1.7.2.jar
sh startup.sh -m standalone
Sentinel
采用懒加载机制,需要手动发起一次请求才可以被监控到,否则Sentinel Dashboard
为空。
@SentinelResource
file.conf
service {
#vgroup->rgroup
vgroup_mapping.my_test_tx_group = "fsp_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"
}
store {
mode = "db"
## database store
db {
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"
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
}
}
MySQL
建库seata
seata
建表,执行 conf/db_store.sql
registry.conf
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos" ##########修改为 nacos
nacos {
serverAddr = "localhost:8848" ###### 为 nacos 修改连接配置
namespace = ""
cluster = "default"
}
}
nacos
seata
这里会创建三个服务,一个订单服务,一个库存服务,一个银行账户服务。
下面开始创建业务数据库
执行项目中的seata.sql
文件,执行后会生成三个数据库,订单、库存、银行账户,以及每个数据库中的基本表即回滚日志表。
启动nacos
单机模式
启动seata
启动seata-order-service2001
启动seata-storage-service2002
启动seata-account-service2003
localhost:2001/order/create?userId=1&productId=1&count=10&money=100
天坑: 项目中
resources/file.conf
与seata/conf/file.conf
有一点些许的不同,如果直接将seata/conf/file.conf
复制进项目的话,会报 Netty 连接失败的问题。
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。