服务化改造实践(三) | Dubbo + Zipkin

随着业务的发展,应用的规模不断的扩大,传统的应用架构无法满足诉求,服务化架构改造势在必行,以 Dubbo 为代表的分布式服务框架成为了服务化改造架构中的基石。随着微服务理念逐渐被大众接受,应用进一步向更细粒度拆分,并且,不同的应用由不同的开发团队独立负责,整个分布式系统变得十分复杂。没有人能够清晰及时的知道当前系统整体的依赖关系。当出现问题时,也无法及时知道具体是链路上的哪个环节出了问题。

在这个背景下,Google 发表了 Dapper 的论文,描述了如何通过一个分布式追踪系统解决上述问题。基于该论文,各大互联网公司实现并部署了自己的分布式追踪系统,其中比较出名的有阿里巴巴的 EagleEye。本文中提到的 Zipkin 是 Twitter 公司开源的分布式追踪系统。下面会详细介绍如何在 Dubbo 中使用 Zipkin 来实现分布式追踪。

Zipkin 简介

Zipkin 是基于 Dapper 论文实现,由 Twitter 开源的分布式追踪系统,通过收集分布式服务执行时间的信息来达到追踪服务调用链路、以及分析服务执行延迟等目的。

Zipkin 架构

 

Collector 收集器、Storage 存储、API、UI 用户界面等几部分构成了 Zipkin Server 部分,对应于 GitHub 上 openzipkin/zipkin 这个项目。而收集应用中调用的耗时信息并将其上报的组件与应用共生,并拥有各个语言的实现版本,其中 Java 的实现是 GitHub 上 openzipkin/brave。除了 Java 客户端实现之外,openzipkin 还提供了许多其他语言的实现,其中包括了 go、php、JavaScript、.net、ruby 等,具体列表可以参阅 Zipkin 的 Exiting instrumentations。

Zipkin 的工作过程

当用户发起一次调用时,Zipkin 的客户端会在入口处为整条调用链路生成一个全局唯一的 trace id,并为这条链路中的每一次分布式调用生成一个 span id。span 与 span 之间可以有父子嵌套关系,代表分布式调用中的上下游关系。span 和 span 之间可以是兄弟关系,代表当前调用下的两次子调用。一个 trace 由一组 span 组成,可以看成是由 trace 为根节点,span 为若干个子节点的一棵树。

 

Span 由调用边界来分隔,在 Zipkin 中,调用边界由以下四个 annotation 来表示:

  • cs - Clent Sent 客户端发送了请求
  • sr - Server Receive 服务端接受到请求
  • ss - Server Send 服务端处理完毕,向客户端发送回应
  • cr - Client Receive 客户端收到结果

显然,通过这四个 annotation 上的时间戳,可以轻易的知道一次完整的调用在不同阶段的耗时,比如:

  • sr - cs 代表了请求在网络上的耗时
  • ss - sr 代表了服务端处理请求的耗时
  • cr - ss 代表了回应在网络上的耗时
  • cr - cs 代表了一次调用的整体耗时

Zipkin 会将 trace 相关的信息在调用链路上传递,并在每个调用边界结束时异步的把当前调用的耗时信息上报给 Zipkin Server。Zipkin Server 在收到 trace 信息后,将其存储起来,Zipkin 支持的存储类型有 inMemory、MySql、Cassandra、以及 ElasticsSearch 几种方式。随后 Zipkin 的 Web UI 会通过 API 访问的方式从存储中将 trace 信息提取出来分析并展示,如下图所示:

 

在 Dubbo 中使用

由于 Brave 对 Dubbo 已经主动做了支持,在 Dubbo 中集成基于 Zipkin 的链路追踪变的十分简单。下面会按照 Brave 中关于 Dubbo RPC 支持的指引来说明如何在 Dubbo 中使用 Zipkin。

安装 Zipkin Server

按照 Zipkin 官方文档中的快速开始 来安装 Zipkin,如下所示:

$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
$ java -jar zipkin.jar

按照这种方式安装的 Zipkin Server 使用的存储类型是 inMemory 的。当服务器停机之后,所有收集到的 trace 信息会丢失,不适用于生产系统。如果在生产系统中使用,需要配置另外的存储类型。Zipkin 支持 MySql、Cassandra、和 ElasticSearch。推荐使用 Cassandra 和 ElasticSearch,相关的配置请自行查阅官方文档。

本文为了演示方便,使用的存储是 inMemory 类型。成功启动之后,可以在终端看到如下的提示:

$ java -jar zipkin.jar
Picked up JAVA_TOOL_OPTIONS: -Djava.awt.headless=true**********        ***            ***            ****            ****          ****        **********************                          **********                           ****                                 **************************************************************************************                           ****                                 *******                          *************      **     *****     ** **       **     **   ****       **     **  *     ***         **     **** ****        **     *****     ****        **     **  *********     **     **        **  **      **     **   **:: Powered by Spring Boot ::         (v2.0.5.RELEASE)...o.s.b.w.e.u.UndertowServletWebServer     : Undertow started on port(s) 9411 (http) with context path ''
2018-10-10 18:40:31.605  INFO 21072 --- [           main] z.s.ZipkinServer                         : Started ZipkinServer in 6.835 seconds (JVM running for 8.35)

然后在浏览器中访问 http://localhost:9411 验证 WEB 界面。

配置 Maven 依赖

引入 Brave 依赖

新建一个新的 Java 工程,并在 pom.xml 中引入 Brave 相关的依赖如下:

    <properties><brave.version>5.4.2</brave.version><zipkin-reporter.version>2.7.9</zipkin-reporter.version></properties><dependencyManagement><dependencies><!-- 引入 zipkin brave 的 BOM 文件 --><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-bom</artifactId><version>${brave.version}</version><type>pom</type><scope>import</scope></dependency><!-- 引入 zipkin repoter 的 BOM 文件 --><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-reporter-bom</artifactId><version>${zipkin-reporter.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><!-- 1. brave 对 dubbo 的集成 --><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-instrumentation-dubbo-rpc</artifactId></dependency><!-- 2. brave 的 spring bean 支持 --><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-spring-beans</artifactId></dependency><!-- 3. 在 SLF4J 的 MDC (Mapped Diagnostic Context) 中支持 traceId 和 spanId --><dependency><groupId>io.zipkin.brave</groupId><artifactId>brave-context-slf4j</artifactId></dependency><!-- 4. 使用 okhttp3 作为 reporter --><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-sender-okhttp3</artifactId></dependency></dependencies>

其中:

  1. 引入 brave-instrumentation-dubbo-rpc,brave 对 dubbo 的支持:https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/README.md
  2. 引入 brave-spring-beans,brave 对 spring bean 的支持:https://github.com/openzipkin/brave/blob/master/spring-beans/README.md
  3. 引入 brave-context-slf4j,brave 对 SLF4J 的支持,可以在 MDC 中使用 traceId 和 spanId:https://github.com/openzipkin/brave/blob/master/context/slf4j/README.md
  4. 引入 zipkin-sender-okhttp3,使用 okhttp3 上报数据:https://github.com/openzipkin/zipkin-reporter-java

引入 Dubbo 相关依赖

Dubbo 相关的依赖是 Dubbo 本身以及 Zookeeper 客户端,在下面的例子中,我们将会使用独立的 Zookeeper Server 作为服务发现。

    <dependencies><!-- 1. Zookeeper 客户端依赖 --><dependency><groupId>org.apache.curator</groupId><artifactId>curator-framework</artifactId><version>2.12.0</version><exclusions><exclusion><groupId>io.netty</groupId><artifactId>netty</artifactId></exclusion></exclusions></dependency><!-- 2. Dubbo 依赖 --><dependency><groupId>com.alibaba</groupId><artifactId>dubbo</artifactId><version>2.6.2</version></dependency></dependencies>

其中:

  1. Dubbo 这里依赖独立的 Zookeeper Server 做服务发现,这里使用的客户端是 Curator
  2. 引入 Dubbo 框架的依赖,原则上 2.6 的任何版本都是工作的,这里使用的是 2.6.2 版本

实现

我们这里构造的场景是一个有两个节点的服务依赖链,也就是,当一个 Dubbo 客户端调用服务 A 时,服务 A 将会继续调用服务 B。在这个例子中,服务 A 是 greeting service,它所依赖的下游服务服务 B 是 hello service。

定义服务接口

为此需要事先定义两个服务接口 GreetingService 以及 HelloService

  1. com.alibaba.dubbo.samples.api.GreetingService

    package com.alibaba.dubbo.samples.api;public interface GreetingService {String greeting(String message);
    }
  2. com.alibaba.dubbo.samples.api.HelloService

    package com.alibaba.dubbo.samples.api;public interface HelloService {String hello(String message);
    }

实现服务接口

为了区分对待,所有和 HelloService 相关的实现代码都放在 hello 子包下,同理 GreetingService 相关的放在 greeting 子包下。

  1. 实现 com.alibaba.dubbo.samples.api.HelloService

    package com.alibaba.dubbo.samples.service.hello;import com.alibaba.dubbo.samples.api.HelloService;import java.util.Random;public class HelloServiceImpl implements HelloService {@Overridepublic String hello(String message) {try {// 通过 sleep 模拟业务逻辑处理时间Thread.sleep(new Random(System.currentTimeMillis()).nextInt(1000));} catch (InterruptedException e) {// no op}return "hello, " + message;}
    }
  2. 实现 com.alibaba.dubbo.samples.api.GreetingService

    package com.alibaba.dubbo.samples.service.greeting;import com.alibaba.dubbo.samples.api.GreetingService;
    import com.alibaba.dubbo.samples.api.HelloService;import java.util.Random;public class GreetingServiceImpl implements GreetingService {// 下游依赖服务,运行时靠 spring 容器注入 HelloService 的服务代理private HelloService helloService;public void setHelloService(HelloService helloService) {this.helloService = helloService;}@Overridepublic String greeting(String message) {try {// 通过 sleep 模拟业务逻辑处理时间Thread.sleep(new Random(System.currentTimeMillis()).nextInt(1000));} catch (InterruptedException e) {// no op}return "greeting, " + helloService.hello(message);}
    }

    这里需要注意的是,GreetingServiceImpl 的实现中声明了一个类型是 HelloService 的成员变量,并在 greeting 方法中,执行完自己逻辑之后又调用了 HelloService 上的 hello 方法。这里的 helloService 的实现将会在运行态由外部注入,注入的不是 HelloServiceImpl 的实现,而是 HelloService 的远程调用代理。通过这样的方式,完成了在一个 Dubbo 服务中继续调用另一个远程 Dubbo 服务的目的。从链路追踪的角度来说,客户端调用 GreetingService 是一个 span,GreetingService 调用 HelloService 是另一个 span,并且两者有父子关系,同属于一个 trace,也就是属于同一条调用链路。

    另外,在 GreetingServiceImpl 和 HelloServiceImpl 的实现中,通过 Thread.sleep 来模拟了处理业务逻辑的耗时,以便在 Zipkin UI 上更好的展示。

配置

为了专注在展示如何使用 Zipkin 这一点上,本文在配置和编程模型上没有采用更多的高级技术,而是使用了最传统的 Spring XML 的配置方式,帮助读者理解。更高级的通过 annotation 甚至 spring boot 的方式,读者可以自行查阅 Dubbo 和 Zipkin 相关的文档。

  1. 暴露 HelloService 服务

    在 resouces/spring/hello-service.xml 中增加以下的配置来将 HelloServiceImpl 暴露成一个 Dubbo 服务:

    • 使用了本地启动的 Zookeeper Server 作为注册中心,地址为默认值 zookeeper://127.0.0.1:2181
    • 用 Dubbo 原生服务在端口 20880 上暴露服务
    • 将 HelloServiceImpl 注册成 id 是 helloService 的 Spring Bean,这样就可以在后续的 <dubbo:service> 中引用到这个实现类
    • 通过 <dubbo:service> 将 HelloServiceImpl 暴露成 Dubbo 服务
        <!-- 定义 HelloService 的应用名 --><dubbo:application name="hello-service-provider"/><!-- 指定注册中心地址 --><dubbo:registry address="zookeeper://127.0.0.1:2181"/><!-- 使用 Dubbo 原生协议在 20880 端口上暴露服务 --><dubbo:protocol name="dubbo" port="20880"/><!-- 将 HelloServiceImpl 的实现声明成一个 spring bean --><bean id="helloService" class="com.alibaba.dubbo.samples.service.hello.HelloServiceImpl"/><!-- 将 HelloServiceImpl 声明成一个 Dubbo 服务 --><dubbo:service interface="com.alibaba.dubbo.samples.api.HelloService" ref="helloService"/>
  2. 增加 Zipkin 相关的配置

    在 resources/spring/hello-service.xml 中增加 Zipkin 相关的配置:

    • 修改 dubbo 服务暴露的配置,添加 Zipkin 的 tracing filter 到 Dubbo 的 filter chain 中
    • 按照 https://github.com/openzipkin/brave/blob/master/spring-beans/README.md 来配置 Zipkin 的 sender 和 tracing 的 spring bean
        <!-- 1. 修改 dubbo 服务暴露配置,在 filter chain 中增加 zipkin 的 tracing 过滤器 --><dubbo:service interface="com.alibaba.dubbo.samples.api.HelloService" ref="helloService" filter="tracing"/><!-- 2. zipkin 相关的配置 --><!-- 使用 OKHttp 来发送 trace 信息到 Zipkin Server。这里的 Zipkin Server 启动在本地 --><bean id="sender" class="zipkin2.reporter.beans.OkHttpSenderFactoryBean"><property name="endpoint" value="http://localhost:9411/api/v2/spans"/></bean><bean id="tracing" class="brave.spring.beans.TracingFactoryBean"><property name="localServiceName" value="hello-service"/><property name="spanReporter"><bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean"><property name="sender" ref="sender"/><!-- wait up to half a second for any in-flight spans on close --><property name="closeTimeout" value="500"/></bean></property><property name="currentTraceContext"><bean class="brave.spring.beans.CurrentTraceContextFactoryBean"><property name="scopeDecorators"><bean class="brave.context.slf4j.MDCScopeDecorator" factory-method="create"/></property></bean></property></bean>
  3. 增加 HelloService 的启动类

    在 com.alibaba.dubbo.samples.service.hello.Application 中通过 ClassPathXmlApplicationContext 读取 刚才配置的 spring/hello-service.xml 来初始化一个 spring context 并启动

    package com.alibaba.dubbo.samples.service.hello;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.io.IOException;public class Application {public static void main(String[] args) throws IOException {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/hello-service.xml");context.start();System.out.println("Hello service started");// press any key to exitSystem.in.read();}
    }
  4. 暴露 GreetingService 服务,并使用 Zipkin

    在 resources/spring/greeting-service.xml 中配置 GreetingService。相关步骤与 HelloService 类似,不再赘述,重点关注如何在 GreetingService 中配置下游服务的依赖。完整的 XML 配置如下:

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"><!-- 1. 定义 GreetingService 的应用名 --><dubbo:application name="greeting-service-provider"/><!-- 2. 指定注册中心地址 --><dubbo:registry address="zookeeper://127.0.0.1:2181"/><!-- 3. 使用 Dubbo 原生协议在 20881 端口上暴露服务 --><dubbo:protocol name="dubbo" port="20881"/><!-- 4. 声明 HelloService 的远程代理,并在 Dubbo 的 filter chain 中增加 tracing filter --><dubbo:reference id="helloService" check="false" interface="com.alibaba.dubbo.samples.api.HelloService" filter="tracing"/><!-- 5. 将 GreetingServiceImpl 的实现声明成一个 spring bean,并将 HelloService 的远程代理装配进去 --><bean id="greetingService" class="com.alibaba.dubbo.samples.service.greeting.GreetingServiceImpl"><property name="helloService" ref="helloService"/></bean><!-- 6. 将 GreetingServiceImpl 声明成一个 Dubbo 服务,并在 Dubbo 的 filter chain 中增加 tracing filter --><dubbo:service interface="com.alibaba.dubbo.samples.api.GreetingService" ref="greetingService" filter="tracing"/><!-- 7. zipkin 相关的配置 --><bean id="sender" class="zipkin2.reporter.beans.OkHttpSenderFactoryBean"><property name="endpoint" value="http://localhost:9411/api/v2/spans"/></bean><bean id="tracing" class="brave.spring.beans.TracingFactoryBean"><property name="localServiceName" value="greeting-service"/><property name="spanReporter"><bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean"><property name="sender" ref="sender"/><!-- wait up to half a second for any in-flight spans on close --><property name="closeTimeout" value="500"/></bean></property><property name="currentTraceContext"><bean class="brave.spring.beans.CurrentTraceContextFactoryBean"><property name="scopeDecorators"><bean class="brave.context.slf4j.MDCScopeDecorator" factory-method="create"/></property></bean></property></bean>
    </beans>

    这里的配置与上面的 HelloService 类似,需要重点关注的有两点:

    • 第 3 步中注意服务需要暴露在不同的端口上,否则会和 HelloService 冲突,本例中选择的是 20881 这个端口
    • 通过第 4 步先声明 HelloService 的远程代理,然后在第 5 步中将其组装给 GreetingService 来完成服务上下游依赖的声明

    增加 GreeeingService 的启动类,与 HelloService 类似,通过 spring/greeting-service.xml 的配置来初始化一个新的 spring context 来完成。

   package com.alibaba.dubbo.samples.service.greeting;import org.springframework.context.support.ClassPathXmlApplicationContext;import java.io.IOException;public class Application {public static void main(String[] args) throws IOException {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/greeting-service.xml");context.start();System.out.println("Greeting service started");// press any key to exitSystem.in.read();}}
  1. 实现客户端

    通过 resources/spring/client.xml 初始化一个 spring context,从其中获取 GreetingService 的远程代理,发起远程调用。

    package com.alibaba.dubbo.samples.client;import com.alibaba.dubbo.samples.api.GreetingService;
    import org.springframework.context.support.ClassPathXmlApplicationContext;public class Application {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/client.xml");context.start();// 获取远程代理并发起调用GreetingService greetingService = (GreetingService) context.getBean("greetingService");System.out.println(greetingService.greeting("world"));}
    }

    resource/spring/client.xml 中的配置与 Dubbo 服务的配置类似,主要是配置远程代理,以及配置 Zipkin

    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"xmlns="http://www.springframework.org/schema/beans"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"><!-- 1. 定义 dubbo 客户端的应用名 --><dubbo:application name="dubbo-client"/><!-- 2. 指定注册中心地址 --><dubbo:registry address="zookeeper://127.0.0.1:2181"/><!-- 3. 声明 GreetingService 的远程代理,并在 Dubbo 的 filter chain 中增加 tracing filter --><dubbo:reference id="greetingService" check="false" interface="com.alibaba.dubbo.samples.api.GreetingService" filter="tracing"/><!-- 4. zipkin 相关的配置 --><bean id="sender" class="zipkin2.reporter.beans.OkHttpSenderFactoryBean"><property name="endpoint" value="http://localhost:9411/api/v2/spans"/></bean><bean id="tracing" class="brave.spring.beans.TracingFactoryBean"><property name="localServiceName" value="client"/><property name="spanReporter"><bean class="zipkin2.reporter.beans.AsyncReporterFactoryBean"><property name="sender" ref="sender"/><!-- wait up to half a second for any in-flight spans on close --><property name="closeTimeout" value="500"/></bean></property><property name="currentTraceContext"><bean class="brave.spring.beans.CurrentTraceContextFactoryBean"><property name="scopeDecorators"><bean class="brave.context.slf4j.MDCScopeDecorator" factory-method="create"/></property></bean></property></bean>
    </beans>

完成之后的工程的目录结构如下:

image-20181012141859701.png | left | 747x1030

 

运行

现在让我们把整个链路运行起来,看看 Zipkin 链路追踪的效果。

启动 Zookeeper Server

执行以下命令在本地启动一个 Zookeeper Server,如果没有安装,请自行从 ZooKeeper 官网 下载:

$ zkServer start

启动 Zipkin Server

执行以下命令在本地启动一个 Zipkin Server:

$ curl -sSL https://zipkin.io/quickstart.sh | bash -s
$ java -jar zipkin.jar

启动 HelloService

使用下面的命令启动 HelloService,当然也可以直接在 IDE 中启动:

$ mvn exec:java -Dexec.mainClass=com.alibaba.dubbo.samples.service.hello.Application

启动成功后应该可以在终端上看到 “Hello service started” 的字样。

启动 GreetingService

使用下面的命令启动 GreetingService,当然也可以直接在 IDE 中启动:

$ mvn exec:java -Dexec.mainClass=com.alibaba.dubbo.samples.service.greeting.Application

启动成功后应该可以在终端上看到 “Greeting service started” 的字样。

运行 Dubbo 客户端

使用下面的命令运行 Dubbo 客户端向 GreetingService 发起远程调用,当然也可以直接在 IDE 中运行:

$ mvn exec:java -Dexec.mainClass=com.alibaba.dubbo.samples.client.Application

执行成功后,客户端会在终端上输出 “greeting, hello, world”。

链路追踪

打开浏览器访问 "http://localhost:9411" 并通过 "Find Traces" 按钮来搜索,可以找到刚刚调用的链路追踪,效果如下图所示:

 

还可以进一步的选择每一个 span 来查看本次调用边界内的详情,比如,hello-service 这个 span 的详情如下:

 

总结

本文介绍了链路追踪的基本概念以及 Zipkin 的基本用法,然后用 Dubbo 构建了一条最简单的调用链路,并引入了 Zipkin 做全链路追踪。由于 Zipkin 对 Dubbo 做了很好的支持,整个集成的过程还是十分简单明了的。

Zipkin 对 Dubbo 的支持是构建在 Dubbo 的 filter 扩展机制上的,有兴趣的读者可以通过 https://github.com/openzipkin/brave/blob/master/instrumentation/dubbo-rpc/src/main/java/brave/dubbo/rpc/TracingFilter.java 了解其实现细节。

本文中涉及的例子可以从 https://github.com/dubbo/dubbo-samples 中的 "dubbo-samples-zipkin" 子模块中获取。另外,spring-cloud-sleth 2.0 中开始 正式支持 Dubbo,相关的文章和例子后续计划提供。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/520715.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于TableStore的亿级订单管理解决方案

一、方案背景 订单系统存在于各行各业&#xff0c;如电商订单、银行流水、运营商话费账单等&#xff0c;是一个非常广泛、通用的系统。对于这类系统&#xff0c;在过去十几年发展中已经形成了经典的做法。但是随着互联网的发展&#xff0c;以及各企业对数据的重视&#xff0c;…

mybatis-plus的 mapper.xml 路径配置的坑

mybatis-plus今天遇到一个问题&#xff0c;就是mybatis 没有读取到mapper.xml 文件。 #实体扫描&#xff0c;多个package用逗号或者分号分隔 mybatis-plus:typeAliasesPackage: com.gblfy.springboot.mybatisplus.entitymapper-locations:- classpath*:com/gblfy/springboot/*…

加速布局无服务器生态,腾讯云与Serverless.com达成全球战略合作!

在云计算技术领域&#xff0c;“Serverless&#xff08;无服务器&#xff09;”作为一种新型的软件设计架构正在快速崛起。作为继虚拟机、容器后的第三代通用计算平台&#xff0c;Serverless技术也一直是腾讯云原生的重点发力领域。 近日&#xff0c;在由腾讯云主办的首届Tech…

阿里云周源:一篇文章读懂四代视频加密技术演进

在刚刚圆满落幕的LiveVideoStackCon峰会上&#xff0c;阿里云高级技术专家周源进行了《视频加密和DRM的实施实践》主题分享。周源&#xff0c;有十多年音视频研发经验&#xff0c;之前在淘宝视频负责开放平台&#xff0c;目前在阿里云视频云部门负责媒体处理&#xff0c;在大规…

云原生数据库如何打造业务弹性

云计算带来了业务弹性上的极大优势&#xff0c;阿里云数据库高级产品专家时慢从应用架构的变迁&#xff0c;客户实战案例&#xff0c;业务分析等方面详细介绍POLARDB&#xff0c;及如何利用POLARDB设计互联网创新型应用的数据库架构。 应用架构的变迁——为什么我们需要超级MyS…

SpringMVC 集成 mybatisPlus

文章目录一、基础配置1. pom2. web.xml二、配置文件2.1.spring-context.xml2.2. spring-datasource.xml2.3. spring-mvc.xml2.4. jdbc.properties2.5. logback.xml三、基础类3.1. 实体类3.2. 接口类3.3. 接口映射xml3.4. service接口3.5. 接口实现类3.6. 控制层四、数据库方面4…

四大开源项目联合发布 腾讯已成Github全球贡献前十公司!

近日在Techo开发者大会上&#xff0c;腾讯正式对四大重点开源项目进行了联合发布&#xff0c;包括分布式消息中间件TubeMQ、基于最主流的 OpenJDK8开发的Tencent Kona JDK、分布式HTAP数据库 TBase&#xff0c;以及企业级容器平台TKEStack。 截至目前&#xff0c;腾讯已经在Gi…

实践 | Sentinel 扩展性设计

Sentinel 提供多样的 SPI 接口用于提供扩展的能力。用户可以在用同一个 sentinel-core 的基础上自行扩展接口实现&#xff0c;从而可以方便地给 Sentinel 添加自定义的逻辑。 初始化逻辑扩展机制 为了统一初始化的流程&#xff0c;我们抽象出了 InitFunc 接口代表 Sentinel 的…

android 各版本市占率,Android各版本市占率:果冻豆遥遥领先

近日&#xff0c;谷歌公布了最新Android系统各版本的市场占有率。虽说已发布两年之久且推出三个版本的果冻豆系统出现了小幅下滑&#xff0c;但60.8%的市占率依然遥遥领先其它各版本。Android各版本市占率&#xff1a;果冻豆遥遥领先(图片来源于cnbeta)从 谷歌统计数据显示&…

腾讯首度披露基础架构演进史:“海量之道”进化“生而为云”

近日腾讯Techo开发者大会在北京召开。会上腾讯云副总裁、云架构平台部总经理谢明首次对外披露了腾讯基础设施演进与创新历程。他介绍在微信、QQ等国民级业务不断发展的背后&#xff0c;包括服务器、网络、IDC、计算、存储、数据库等在内的基础设施和技术架构一直在不断进化&…

阿里云专家穆轩的《杭州九年程序员之“修炼”手册》

对于一个从未到过南方的内蒙汉子来说&#xff0c;北京的大学一直是中学时憧憬的殿堂&#xff0c;而离家上千公里浙江大学&#xff0c;则是从来没有考虑过的地方。机缘巧合之下&#xff0c;被一位年近七旬的浙大老师说服&#xff0c;我自此开始了南下“修炼”之旅。没想到转眼间…

主流开源开发者工具落地阿里云,进一步提升开发者体验

在云计算大数据时代&#xff0c;企业的不断上云&#xff0c;业务的不断发展&#xff0c;技术架构的不断演进&#xff0c;导致资源、应用和数据的管理成本不断增加&#xff0c;运维难度不断加大。业务场景的不断和复杂和变化&#xff0c;不得不引起我们更多的思考&#xff1a; …

SpringBoot 集成 mybatisPlus

文章目录一、1. pom2. application.yml3. dao层接口集成baseMapper4. 启动类上扫描5. 创建数据库6. 初始化表结构7. 浏览器验证8. 源码地址一、 1. pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/P…

让开发变得更简单 | 阿里云中间件推出全新开发者服务

要码出未来&#xff0c;除了程序员专属的节日福利&#xff0c;还需要实打实的为程序员解决手头的难题。 10月24日&#xff0c;阿里云中间件推出全新开发者服务&#xff0c;发布3款开发工具&#xff0c;包括Alibaba Cloud Toolkit 、链路追踪Tracing Analysis和应用高可用服务AH…

免费!这里有一份开发者进阶“宝典”求带走

戳蓝字“CSDN云计算”关注我们哦&#xff01;作为开发者&#xff0c;无论是前端还是后端&#xff0c;做机器学习还是云计算、架构&#xff0c;保持对技术的敏感性都是非常重要的事。新技术一般发源于人力、财力等各方面资源都很雄厚的大厂&#xff0c;经过时间的沉淀逐渐成为技…

阿里云发布多款云管工具,任何角色都可以轻松完成云上运维

无论是在传统的开发过程&#xff0c;还是在云上&#xff0c;运维都是一个十分重要而又繁重的工作。随着企业规模的扩大&#xff0c;系统架构的复杂度在增加&#xff0c;部署规模也在不断扩大&#xff0c;控制台不再能满足其需求&#xff0c;需要一个便捷、实用的运维系统或者运…

阿里云容器技术专家莫源:乘风踏雪归来,仍是此间少年

我叫刘中巍&#xff0c;花名莫源&#xff0c;是阿里云容器服务团队的技术专家&#xff0c;13年加入阿里云&#xff0c;从零开始参与多款云产品的研发。在1024开发者节之际&#xff0c;来分享下自己的成长故事。 “平凡但不安分”的男孩 我是一个来自北方的孩子&#xff0c;从小…

12306 的技术扒光在你面前,100 万人如何抢 1 万张票

戳蓝字“CSDN云计算”关注我们哦&#xff01;作者 | IT牧场责编 | 阿秃12306 抢票&#xff0c;极限并发带来的思考每到节假日期间&#xff0c;一二线城市返乡、外出游玩的人们几乎都面临着一个问题&#xff1a;抢火车票&#xff01;虽然现在大多数情况下都能订到票&#xff0…

android monkey优化,GitHub - baozhida/AndroidMonkey: 这个项目是CrashMonkey4Android可执行文件,修复了一些bug,做了一些优化...

简介这个项目是CrashMonkey4Android可执行文件原版不支持64位java&#xff0c;只支持32位的此版本支持java 64位&#xff0c;并且修改了一些内部逻辑&#xff0c;把CrashMonkey4Android 和CrashMonkey4Android_tradefederation 重新打包2017-3-13更新1.去掉了每个monkey操作时候…