需要源码私信我
1、项目介绍
此优乐购电商平台项目属于b2b模式的线上商城,支持用户在线浏览商品,在线搜索商品,并且可以将喜欢的商品加入购物车从而下单购买商品,同时支持线上支付,支付模式支持支付宝、微信。用户还可以参与低价商品秒杀。
SpringBoot+SpringCloud+Redis+Mybatis+Shiro+Nginx +Vue+
Element-UI+Thymeleaf+Nacos+Seata+Sentinel+Sleuth&Zpkin+RabbitMQ
IDEA、JDK1.8、Tomcat、MySQL、Maven、Git
用户管理、商品管理、商品类别管理、订单管理、支付管理、地址管理、评论管理等
LInux
解压linux 压缩包后,导入虚拟机,输入用户名:root,密码:sasa,
《1.进入/etc/sysconfig/network-scripts/--》《2. vi ifcfg-ens33--》3.修改 --
192.168.237.75=说明:进入《编辑》点击《虚拟网络编辑器》查看《Vmnet8,子网地址,第二点后的字段如192.168.237.5 为 237 》 DNS1="192.168.237.1" IPADDR="192.168.237.75"
GATEWAY="192.168.237.75"
《
TYPE="Ethernet"
PROXY_METHOD="none"
BROWSER_ONLY="no"
BOOTPROTO="static"
DEFROUTE="yes"
IPV4_FAILURE_FATAL="no"
IPV6INIT="yes"
IPV6_AUTOCONF="yes"
IPV6_DEFROUTE="yes"
IPV6_FAILURE_FATAL="no"
IPV6_ADDR_GEN_MODE="stable-privacy"
NAME="ens33"
UUID="9bf60c47-d18b-4973-9828-d6c3f857ba2e"
DEVICE="ens33"
ONBOOT="yes"
IPADDR="192.168.237.75"
PREFIX="24"
GATEWAY="192.168.237.75"
DNS1="192.168.237.1"
IPV6_PRIVACY="no"
》4---》reboot(重启)
5---》
5.1cd /data/nginx/conf -->
5.2 vi nginx.conf
6-- 》
修改 upstream zmall{
server 192.168.237.1:7000;
}
《
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
#upstream ruoyi-admin-servers {
# ip_hash;
# server ruoyi-admin01:8080;
# server ruoyi-admin02:8080;
# }
upstream nacos-cluster {
ip_hash;
server nacos01:8848;
server nacos02:8848;
server nacos03:8848;
}
upstream zmall{
server 192.168.233.1:7000;
}
server {
listen 80;
server_name *.zmall.com;
charset utf-8;
location /nacos/ {
proxy_pass http://nacos-cluster;
}
location /static/ {
root /usr/share/nginx/html;
}
location / {
# proxy_pass 将监听到的请求转发到对应的upstream网关地址。即在此完成了访问网址-> nginx -> 网关
proxy_pass http://zmall;
# proxy_set_header 给通过nginx 的请求添加请求头的部分信息
proxy_set_header Host $host;
}
#location /prod-api/ {
#proxy_set_header Host $http_host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header REMOTE-HOST $remote_addr;
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_pass http://ruoyi-admin-servers/; #设置代理转发地址
#}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
》
java 项目篇
将电商项目解压后,导入到idea,配置maven
下载SwitchHosts ,点击加号一个本地的hosts ,标题随意
内容:
192.168.237.75 zmall-server
192.168.237.75 zmall.com
192.168.237.75 product.zmall.com
192.168.237.75 order.zmall.com
192.168.237.75 cart.zmall.com
192.168.237.75 zmall-admin.com
192.168.237.75 auth.zmall.com
192.168.237.75 skill.zmall.com
192.168.237.75 admin.zmall.com
127.0.0.1 ssoserver.com
127.0.0.1 client1.com
127.0.0.1 product.zmall1.com
启动所有的项目
ZmallOrderApplication2
ZmallGatewayApplication
ZmallCartApplication
ZmallProductApplication
ZmallAdminApplication
ZmallOrderApplication
欧克,到这里应该就都可以了,如果你想更深入了解的话就继续往下看吧
application.yml 与 boostart.yml
application.yml SpringBoot 应用的自动化配置
boostart.yml 使用有三种场景
1.使用Spring Cloud Config 配置中心时,这时候需要在boostart.yml 配置文件中配置连接外部配置中心的配置属性来加载配置信息
2.一些加密解密的场景
3.一些固定的不能被修改的信息
Sentinel Sentinel 是阿里巴巴开源的一款断路器实现,本身在阿里内部已经被大规模采用,非常稳定。
linux 6.0.1--->
docker pull bladex/sentinel-dashboard:1.8.0
docker run --name sentinel -d -p 8858:8858 --restart always --network net-zmall bladex/sentinel-dashboard:1.8.0
6.1 ---》在zmall_common(公告模块)pom 文件导入依赖
com.alibaba.cloud
spring-cloud-starter-alibaba-sentinel
6.2 ---》在订单模块 中resource 文件夹下,application.yml文件夹下
spring:
cloud:
sentinel:
transport:
port: 9999 #跟控制台交流的端口,随意指定一个未使用的端口即可
dashboard: zmall-server:8858 # 指定控制台服务的地址
web-context-unify: false #关闭自动收敛
eager: true #主动发送心跳 当服务启动时自己主动出现在sentinel 控制台上
6.3 ---》在GateWay模块 中resource 文件夹下,application.yml文件夹下
spring:
cloud:
sentinel:
transport:
port: 9998 #跟控制台交流的端口,随意指定一个未使用的端口即可
dashboard: zmall-server:8858 # 指定控制台服务的地址
web-context-unify: false #关闭自动收敛
eager: true #主动发送心跳 当服务启动时自己主动出现在sentinel 控制台上
6.4---》 重新启动订单服务
访问订单模块下的服务
order.zmall.com/order/prod?pid=733
访问Sentinel Dashboard
输入用户名密码都是:sentinel
点击zmall-order 点击zu点链路,就可看到你所访问的url 了
6.5---》
新建流控,建立如下
(在zmall-order 下只可以对本模块限流,)
只要实现了这个异常
package com.zking.zmall.order.config;
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.fastjson.JSON;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//异常处理页面
@Component
public class ExceptionHandlerPage implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
response.setContentType("application/json;charset=utf-8");
ResponseData data = null;
if (e instanceof FlowException) {
data = new ResponseData(-1, "接口被限流了...");
} else if (e instanceof DegradeException) {
data = new ResponseData(-2, "接口被降级了...");
}
response.getWriter().write(JSON.toJSONString(data));
}
}
@Data
@AllArgsConstructor//全参构造
@NoArgsConstructor//无参构造
class ResponseData {
private int code;
private String message;
}
再次访问你会发现{code:-1, message:"接口被限流了..." }
6.6---》
网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,我们本次采用前 面学过的Sentinel组件来实现网关的限流。Sentinel支持对SpringCloud Gateway、Zuul等主流网关进行限流。
从1.6.0版本开始,Sentinel提供了SpringCloud Gateway的适配模块,可以提供两种资源维度的限流:
route维度:即在Spring配置文件中配置的路由条目,资源名为对应的routeId
自定义API维度:用户可以利用Sentinel提供的API来自定义一些API分组
6.6.1--> 在zmall-common||在zmall-gateway导入依赖
com.alibaba.csp
sentinel-spring-cloud-gateway-adapter
6.6.2---> 编写配置类 基于Sentinel 的Gateway限流是通过其提供的Filter来完成的,使用时只需注入对应的 SentinelGatewayFilter实例以及 SentinelGatewayBlockExceptionHandler 实例即可
推荐使用在sentinel控制台建立流控规则,因为容易。
package com.zking.config;
import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.*;
@Configuration
public class GatewayConfiguration {
private final List viewResolvers;
// 自定义限流异常页面
@PostConstruct
public void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map map = new HashMap<>();
map.put("code", 0);
map.put("message", "接口被限流了");
return ServerResponse.status(HttpStatus.OK).
contentType(MediaType.APPLICATION_JSON_UTF8).
body(BodyInserters.fromObject(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfiguration(ObjectProvider> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
// 初始化一个限流的过滤器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
// 配置初始化的限流参数
@PostConstruct
public void initGatewayRules() {
Set rules = new HashSet<>();
rules.add(
new GatewayFlowRule("product_route") //资源名称,对应路由id
.setCount(1) // 限流阈值
.setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
);
GatewayRuleManager.loadRules(rules);
}
// 配置限流的异常处理器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
6.6.3---> 测试 在一秒钟内多次访问http://zmall.com/prod/detail/1就可以看到限流启作用了。
6.6.4---> 自定义API分组 自定义API分组是一种更细粒度的限流规则定义
// 配置初始化的限流参数
@PostConstruct
public void initGatewayRules() {
// Set rules = new HashSet<>();
// rules.add(
// new GatewayFlowRule("product_route") //资源名称,对应路由id
// .setCount(1) // 限流阈值
// .setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
// );
// GatewayRuleManager.loadRules(rules);
Set rules = new HashSet<>();
rules.add(new GatewayFlowRule("product_api1").setCount(1).setIntervalSec(1));
rules.add(new GatewayFlowRule("product_api2").setCount(1).setIntervalSec(1));
GatewayRuleManager.loadRules(rules);
}
//自定义API分组
@PostConstruct
private void initCustomizedApis() {
Set definitions = new HashSet<>();
ApiDefinition api1 = new ApiDefinition("product_api1")
.setPredicateItems(new HashSet() {
{
// 以/product-serv/product/api1 开头的请求
add(new ApiPathPredicateItem().setPattern("/product-serv/product/api1/**").
setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
ApiDefinition api2 = new ApiDefinition("product_api2")
.setPredicateItems(new HashSet() {
{
// 以/product-serv/product/api2/demo1 完成的url路径匹配
add(new ApiPathPredicateItem().setPattern("/product-serv/product/api2/demo1"));
}});
definitions.add(api1);
definitions.add(api2);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
6.6.5--->新建流控,也可在zmall-gateway下建立如下
(在zmall-gateway下只可以对所有模块限流,网关是所有请求的公共入口,所以可以在网关进行限流)
再次访问你会发现{code:-1, message:"接口被限流了..." }
在大型系统的微服务化构建中,一个系统被拆分成了许多模块。这些模块负责不同的功能,组合成 系统,最终可以提供丰富的功能。在这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建 在不同的软件模块集上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实 现、有可能布在了几千台服务器,横跨多个不同的数据中心,也就意味着这种架构形式也会存在一些问 题:
如何快速发现问题?
如何判断故障影响范围?
如何梳理服务依赖以及依赖的合理性?
如何分析链路性能问题以及实时容量规划?
分布式链路追踪(Distributed Tracing),就是将一次分布式请求还原成调用链路,进行日志记 录,性能监控并将一次分布式请求的调用情况集中展示。比如各个服务节点上的耗时、请求具体到达哪 台机器上、每个服务节点的请求状态等等。
常见的链路追踪技术有下面这些:
cat 由大众点评开源,基于Java开发的实时应用监控平台,包括实时应用监控,业务监控 。 集成 方案是通过代码埋点的方式来实现监控,比如: 拦截器,过滤器等。 对代码的侵入性很大,集成 成本较高。风险较大。
zipkin 由Twitter公司开源,开放源代码分布式的跟踪系统,用于收集服务的定时数据,以解决微 服务架构中的延迟问题,包括:数据的收集、存储、查找和展现。该产品结合spring-cloud-sleuth 使用较为简单, 集成很方便, 但是功能较简单。
pinpoint Pinpoint是韩国人开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点 是支持多种插件,UI功能强大,接入端无代码侵入。
skywalking SkyWalking是本土开源的基于字节码注入的调用链分析,以及应用监控分析工具。特点是支持多 种插件,UI功能较强,接入端无代码侵入。目前已加入Apache孵化器。
Sleuth SpringCloud 提供的分布式系统中链路追踪解决方案。
注意:SpringCloud alibaba技术栈中并没有提供自己的链路追踪技术的,我们可以采用Sleuth + Zinkin来做链路追踪解决方案
SpringCloud Sleuth主要功能就是在分布式系统中提供追踪解决方案。它大量借用了Google Dapper的设计, 先来了解一下Sleuth中的术语和相关概念。
Trace 由一组Trace Id相同的Span串联形成一个树状结构。为了实现请求跟踪,当请求到达分布式系统的 入口端点时,只需要服务跟踪框架为该请求创建一个唯一的标识(即TraceId),同时在分布式系 统内部流转的时候,框架始终保持传递该唯一值,直到整个请求的返回。那么我们就可以使用该唯 一标识将所有的请求串联起来,形成一条完整的请求链路。
Span 代表了一组基本的工作单元。为了统计各处理单元的延迟,当请求到达各个服务组件的时 候,也通过一个唯一标识(SpanId)来标记它的开始、具体过程和结束。通过SpanId的开始和结 束时间戳,就能统计该span的调用时间,除此之外,我们还可以获取如事件的名称。请求信息等 元数据。
Annotation 用它记录一段时间内的事件,内部使用的重要注释: cs(Client Send)客户端发出请求,开始一个请求的生命 sr(Server Received)服务端接受到请求开始进行处理, sr-cs = 网络延迟(服务调用的时间) ss(Server Send)服务端处理完毕准备发送到客户端,ss - sr = 服务器上的请求处理时间 cr(Client Reveived)客户端接受到服务端的响应,请求结束。 cr - sr = 请求的总时间
微服务名称, traceId, spanid,是否将链路的追踪结果输出到第三方平台 [api-gateway,3977125f73391553,3977125f73391553,false] [service-order,3977125f73391553,57547b5bf71f8242,false] [service-product,3977125f73391553,449f5b3f3ef8d5c5,false] 接下来通过之前的项目案例整合Sleuth,完成入门案例的编写。引入Sleuth依赖
org.springframework.cloud
spring-cloud-starter-sleuth
启动微服务,调用之后,我们可以在控制台观察到sleuth的日志输出
其中5399d5cb061971bd 是TraceId, 5399d5cb061971bd 是SpanId,依次调用有一个全局的 TraceId,将调用链路串起来。仔细分析每个微服务的日志,不难看出请求的具体过程。 查看日志文件并不是一个很好的方法,当微服务越来越多日志文件也会越来越多,通过Zipkin可以 将日志聚合,并进行可视化展示和全文检索。
Zipkin 是 Twitter 的一个开源项目,它基于Google Dapper实现,它致力于收集服务的定时数据, 以解决微服务架构中的延迟问题,包括数据的收集、存储、查找和展现。 我们可以使用它来收集各个服务器上请求链路的跟踪数据,并通过它提供的REST API接口来辅助我 们查询跟踪数据以实现对分布式系统的监控程序,从而及时地发现系统中出现的延迟升高问题并找出系 统性能瓶颈的根源。 除了面向开发的 API 接口之外,它也提供了方便的UI组件来帮助我们直观的搜索跟踪信息和分析请 求链路明细,比如:可以查询某段时间内各用户请求的处理时间等。 Zipkin 提供了可插拔数据存储方式:In-Memory、MySql、Cassandra 以及 Elasticsearch。
上图展示了 Zipkin 的基础架构,它主要由 4 个核心组件构成:
Collector:收集器组件,它主要用于处理从外部系统发送过来的跟踪信息,将这些信息转换为 Zipkin内部处理的 Span 格式,以支持后续的存储、分析、展示等功能。
Storage:存储组件,它主要对处理收集器接收到的跟踪信息,默认会将这些信息存储在内存中, 我们也可以修改此存储策略,通过使用其他存储组件将跟踪信息存储到数据库中。
RESTful API:API 组件,它主要用来提供外部访问接口。比如给客户端展示跟踪信息,或是外接 系统访问以实现监控等。
Web UI:UI 组件, 基于API组件实现的上层应用。通过UI组件用户可以方便而有直观地查询和分 析跟踪信息。
Zipkin分为两端,一个是 Zipkin服务端,一个是 Zipkin客户端,客户端也就是微服务的应用。 客户端会 配置服务端的 URL 地址,一旦发生服务间的调用的时候,会被配置在微服务里面的 Sleuth 的监听器监 听,并生成相应的 Trace 和 Span 信息发送给服务端
docker run -d -p 9411:9411 --network net-zmall --name zipkin --restart always openzipkin/zipkin
ZipKin客户端和Sleuth的集成非常简单,只需要在微服务中添加其依赖和配置即可。
第1步:在每zmall-common 模块上添加依赖
org.springframework.cloud
spring-cloud-starter-zipkin
8.3.2---》第2步:添加配置
spring:
zipkin:
base-url: http://zmall-server:9411/ #zipkin server的请求地址
discoveryClientEnabled: false #让nacos把它当成一个URL,而不要当做服务名
sleuth:
sampler:
probability: 1.0 #采样的百分比
8.3.3--》第3步: 访问微服务
在boostart.yml 中配置nacos的信息(可以避免在启动时报错)
spring:
application:
name: zmall-gateway 同resource 文件夹下的application.name: 名字即可
cloud:
nacos:
config:
server-addr: zmall-server:80 # nacos的服务端地址
file-extension: yml # 配置文件格式
extension-configs[0]:
data-id: zmall-common.yml
group: DEFAULT_GROUP
refresh: true
profiles:
active: dev # 环境标识
order.zmall.com/order/prod?pid=733
8.3.4--》第4步: 访问zipkin的UI界面,观察效果
8.4.5---》第5步:点击其中一条记录show,可观察一次访问的详细线路。
Zipkin Server默认会将追踪数据信息保存到内存,但这种方式不适合生产环境。Zipkin支持将追踪 数据持久化到mysql数据库或elasticsearch中。
第1步: 创建mysql数据环境
CREATE TABLE IF NOT EXISTS zipkin_spans (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this
means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL,
`id` BIGINT NOT NULL,
`name` VARCHAR ( 255 ) NOT NULL,
`parent_id` BIGINT,
`debug` BIT ( 1 ),
`start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
`duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query'
) ENGINE = INNODB ROW_FORMAT = COMPRESSED CHARACTER
SET = utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_spans ADD UNIQUE KEY ( `trace_id_high`, `trace_id`, `id` )
COMMENT 'ignore insert on duplicate';
ALTER TABLE zipkin_spans ADD INDEX ( `trace_id_high`, `trace_id`, `id` )
COMMENT 'for joining with zipkin_annotations';
ALTER TABLE zipkin_spans ADD INDEX ( `trace_id_high`, `trace_id` )
COMMENT 'forgetTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX ( `name` )
COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX ( `start_ts` )
COMMENT 'for getTraces ordering and range';
CREATE TABLE IF NOT EXISTS zipkin_annotations (
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this
means the trace uses 128 bit traceIds instead of 64 bit',
`trace_id` BIGINT NOT NULL COMMENT 'coincides with
zipkin_spans.trace_id',
`span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
`a_key` VARCHAR ( 255 ) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
`a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
`a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
`a_timestamp` BIGINT COMMENT 'Used to implement TTL;
SET = utf8 COLLATE utf8_general_ci;
ALTER TABLE zipkin_annotations ADD UNIQUE KEY ( `trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp` )
COMMENT 'Ignore insert on duplicate';
ALTER TABLE zipkin_annotations ADD INDEX ( `trace_id_high`, `trace_id`, `span_id` )
COMMENT 'for joining with zipkin_spans';
ALTER TABLE zipkin_annotations ADD INDEX ( `trace_id_high`, `trace_id` )
COMMENT 'for getTraces/ByIds';
ALTER TABLE zipkin_annotations ADD INDEX ( `endpoint_service_name` )
COMMENT 'for getTraces and getServiceNames';
ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`)
COMMENT 'for dependencies job';
CREATE TABLE IF NOT EXISTS zipkin_dependencies (
`day` DATE NOT NULL,
`parent` VARCHAR(255) NOT NULL,
`child` VARCHAR(255) NOT NULL,
`call_count` BIGINT
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE
utf8_general_ci;
ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`);
Annotation.timestamp or zipkin_spans.timestamp',
`endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_ipv6` BINARY ( 16 ) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
`endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
`endpoint_service_name` VARCHAR ( 255 ) COMMENT 'Null when
Binary/Annotation.endpoint is null'
) ENGINE = INNODB ROW_FORMAT = COMPRESSED CHARACTER
第2步: 在启动ZipKin Server的时候,指定数据保存的mysql的信息
java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=mysql --MYSQL_HOST=127.0.0.1 --MYSQL_TCP_PORT=3306 --MYSQL_DB=shop --MYSQL_USER=root --MYSQL_PASS=sasa
第1步: 下载elasticsearch 下载地址:Elasticsearch 6.8.4 | Elastic 第2步: 启动elasticsearch
第3步: 在启动ZipKin Server的时候,指定数据保存的elasticsearch的信息
java -jar zipkin-server-2.12.9-exec.jar --STORAGE_TYPE=elasticsearch --ESHOST=localhost:9200
spring-boot整合spring-session的自动配置可谓是开箱即用,极其简洁和方便。这篇文章即介绍spring-boot整合spring-session,这里只介绍基于RedisSession的实战。
docker run -itd --name redis01 -p 6379:6379 \
-v /data/redis/conf/redis.conf:/etc/redis/redis.conf \
-v /data/redis/data:/data \
--privileged=true --restart=always \
--network net-kugo redis \
redis-server /etc/redis/redis.conf
9.1redis.conf
bind 0.0.0.0 充许远程访问
requirepass sasa 使用了密码
daemonize no 后台运行
引入spring-session的pom配置,由于spring-boot包含spring-session的starter模块,所以pom中依赖:(
Lettuce
是一个高性能基于Java
编写的Redis
驱动框架,底层集成了Project Reactor
提供天然的反应式编程,通信框架集成了Netty
使用了非阻塞IO
,5.x
版本之后融合了JDK1.8
的异步编程特性,在保证高性能的同时提供了十分丰富易用的API
,5.1