Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >一文让你了解微服务契约测试

一文让你了解微服务契约测试

作者头像
顾翔
发布于 2024-09-10 06:11:12
发布于 2024-09-10 06:11:12
15100
代码可运行
举报
运行总次数:0
代码可运行

谈到微服务,大家都想到契约测试,到底什么是契约测试呢,为什么要使用契约测试呢,关于这样的文章很多,本文将结合Spring Boot让你了解微服务契约测试。

首先我们来看一下微服务,微服务是一种分布式结构,对于一种服务一方为服务的提供者,另一方为服务的消费者。我们用一个虚拟的阿里产品体系做个对比,比如登录这个接口,对于许多电商模块(我们称为服务)要使用,比如:天猫、淘宝、飞猪、盒马。这些登录接口可以由用户服务中台来提供,大家使用统一的登录接口,防止重复开发。

在没有契约测试之前,当用户接口没有提供天猫、淘宝、飞猪、盒马登录使用用户服务中台提供的Stub,用户服务中台提供的Stub由用户服务中台开发团队来维护,当用户服务中台开发完毕,天猫、淘宝、飞猪、盒马登录才使用真正的登录模块。由此可以看到每一个服务提供者模块在开发自身的业务模块之前,还要维护服务Stub模块,这样大大增加了开发成本。

有了契约测试,只要服务提供者提供契约文件及基于契约文件自动产生的stub模块给服务消费者,服务消费者利用契约文件也产生同样的Stub模块,在服务提供者没有开发可用的真正的程序之前,利用Stub模块进行调试。以上是契约测试的一个优点,把维护stub模块变为了维护契约文件,这样大大地节约开发成本;另外还可以发现接口变动问题。

这是最初服务生产者提供的接口body接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"年龄":"37"
"性别":"男"
"姓名":"王睿"
}

服务消费者A提供的接口是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"年龄":"37"
"性别":"男"
}

没有“姓名”,这个是允许的。

服务消费者B提供的接口是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"年龄":"37"
"性别":"男"
"姓名":"王睿"
}

这个与提供者完全一致,当然是允许的。

服务消费者C提供的接口是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"性别":"男"
"姓名":"王睿"
}

没有“年龄”,这个是允许的。

某一天,服务消费者C由于业务要求,需要把姓名中的姓与名拆成两部分,修改了body格式

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"性别":"男"
"姓":"王"
"名":"睿"
}

并提给服务生产者这个接口需求变更,生产者接受了这个请求,将契约文件改为

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"性别":"男"
"姓":"王"
"名":"睿"
}

当这个契约文件分发给各个服务消费者,由于服务消费者A提供的接口是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
"年龄":"37"
"性别":"男"
}

由于没有“姓名”变更不受影响,而服务消费者B提供的接口是

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
“年龄”:"37"
“性别”:"男"    
“姓名”:"王睿"
}

姓名没有拆分,所以测试失败,告知大家,线下协商策略,决定 “姓名”是否修改。

在这里知道相关的服务消费者只有3个,而在实际的产品中服务多达成百上千个,有的是服务生产者。有的是服务消费者,大部分既是服务生产者又是服务消费者。当某一个接口发生变化,不运行契约测试不知道哪些模块会受到变动的影响,另外最后决定接口是否修改,也是根据fail接口的数量及fail接口的优先等级来决定的。

下面我们用一个具体的Spring Boot的案例来进行介绍,在这个案例中,流程是这样的。

  1. 服务生产者开发契约文件程序,自动形成契约文件。
  2. 将形成的契约文件打包上传到GitHub中。
  3. 服务消费者开发之前从GitHub中下载本地契约文件到本地目录下。
  4. 运行测试文件,验证测试是否满足现在的契约文件。

在这里我使用Spring Boot+cucumber+契约测试文章中的案例

服务生产者Spring Boot pom.xml文件如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0"
encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-parent</artifactId>
 <version>3.2.3</version>
 <relativePath/>
<!-- lookup parent from repository -->
 </parent>
 <groupId>com.example</groupId>
 <artifactId>ATMService</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>ATMService</name>
 <description>Demo project for Spring Boot</description>
 <properties>
 <java.version>11</java.version>
 <cucumber.version>6.8.1</cucumber.version>
 <spring-cloud.version>4.1.0</spring-cloud.version>
 <spring-cloud.version>2023.0.0</spring-cloud.version>
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 <snippetsDirectory>${project.build.directory}/generated-snippets</snippetsDirectory>
 </properties>
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
 <scope>test</scope>
 </dependency>
 
 <dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-contract-wiremock</artifactId>
 <scope>test</scope>
 </dependency>
 
 <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-contract-verifier</artifactId>
   <scope>test</scope>
 </dependency>
 
 <dependency>
   <groupId>org.junit.vintage</groupId>
   <artifactId>junit-vintage-engine</artifactId>
   <scope>test</scope>
 </dependency>  
 <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
 </dependency>
 <dependency>
   <groupId>org.springframework.restdocs</groupId>
   <artifactId>spring-restdocs-mockmvc</artifactId>
 </dependency>
 <dependency>
   <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-dependencies</artifactId>
  <version>${spring-cloud.version}</version>
  <type>pom</type>
 </dependency>
<dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-java</artifactId>
  <version>${cucumber.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-spring</artifactId>
  <version>${cucumber.version}</version>
  <scope>test</scope>
</dependency>
<dependency>
  <groupId>io.cucumber</groupId>
  <artifactId>cucumber-junit-platform-engine</artifactId>
  <version>${cucumber.version}</version>
  <scope>test</scope>
</dependency>
</dependencies>
 <dependencyManagement>
   <dependencies>
    <dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-dependencies</artifactId>
       <version>${spring-cloud.version}</version>
       <type>pom</type>
       <scope>import</scope>
    </dependency>
    </dependencies>
 </dependencyManagement>
 <build>
   <plugins>
     <plugin>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-contract-maven-plugin</artifactId>
       <version>4.1.0</version>
       <extensions>true</extensions>
       <configuration>
          <testFramework>JUNIT5</testFramework>
       </configuration>
     </plugin>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
   </plugins>
 </build>
</project>

在test下建立StubsGenerator.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.example.ATMService;
           
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;    
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
           
import org.springframework.cloud.contract.wiremock.restdocs.SpringCloudContractRestDocs;
           
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.restdocs.AutoConfigureRestDocs;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
           
import org.springframework.beans.factory.annotation.Autowired;
               
@AutoConfigureRestDocs(outputDir = "target/stubs/META-INF/com.example")
@AutoConfigureMockMvc
@SpringBootTest
public class StubsGenerator {
  @Autowired
  private MockMvc mockMvc;
  @Autowired
  private MockMvc mockMvc;
  @Test
  public void verify_pin_ok()throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.get("/verify_pin/1111222233?pin=123456")
    .contentType(MediaType.APPLICATION_JSON)
    .accept(MediaType.APPLICATION_JSON))
    .andExpect(status().isOk())
    .andDo(document("verify_pin",SpringCloudContractRestDocs.dslContract()));
  }

  @Test
  public void verify_pin_fail()throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.get("/verify_pin/1111222233?pin=654321")
    .contentType(MediaType.APPLICATION_JSON)
    .accept(MediaType.APPLICATION_JSON))
    .andExpect(status().isOk())
    .andDo(document("verify_pin_fail",SpringCloudContractRestDocs.dslContract()));
  }       
}

程序将模拟一个HTTP请求,并且建立契约文件

  • @AutoConfigureRestDocs(outputDir = "target/stubs/META-INF/com.example")//定义契约文件位置
  • 当/verify_pin/1111222233?pin=123456为Get请求时.andExpect(status().isOk()) //返回状态码为200;返回内容在Controller程序中定义。
  • .andDo(document("verify_pin",SpringCloudContractRestDocs.dslContract()));//建立名为verify_pin的契约文件
  • 当/verify_pin/1111222233?pin=654321为Get请求时
  • .andExpect(status().isOk()) //返回状态码为200;返回内容在Controller程序中定义。
  • .andDo(document("verify_pin_fail",SpringCloudContractRestDocs.dslContract()));//建立名为verify_pin_fail的契约文件

接下来我们看一下main中建立的pageController.java。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.example.ATMService.Controller;
           
import org.springframework.web.bind.annotation.GetMapping;    
import org.springframework.web.bind.annotation.RestController;
           
@RestController
public class pageController {
       @GetMapping("/verify_pin/1111222233")
       public String list(String pin){
              String list = "";
              if (!pin.equals("123456")){
                     list = list + "{\"result\":\"Your PlN is apnalnd\"}";
              }else {
                     list = list + "{\"result\":\"OK\"}";
                    
              }
              return list;
       }
}

@GetMapping("/verify_pin/1111222233")获得路径为"/verify_pin/1111222233"

当参数pin!="123456",返回body体为"{\"result\":\"Your PlN is apnalnd\"}"

否则返回body体为"{\"result\":\"OK\"}"。

用JUnit运行StubsGenerator.java,测试通过

在@AutoConfigureRestDocs(outputDir = "target/stubs/META-INF/com.example")生成契约文件(如果pageController存在错误,系统将产生不了契约文件)。

verify_pin_fail.groovy与verify_pin.groovy是产生的契约文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.springframework.cloud.contract.spec.Contract

Contract.make {
    request {
        method 'GET'
        urlPath('/verify_pin/1111222233')  {
            queryParameters {
                    parameter('''pin''', '''123456''')
            }
        } 
        headers {
            header('''Accept''', '''application/json''')
            header('''Content-Type''', '''application/json;charset=UTF-8''')
        }
    }
    response {
        status 200
        body('''{"result":"OK"}''')
        headers {
            header('''Content-Type''', '''application/json''')
        }
    }
}

verify_pin_fail.groovy

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import org.springframework.cloud.contract.spec.Contract

Contract.make {
    request {
        method 'GET'
        urlPath('/verify_pin/1111222233')  {
            queryParameters {
                    parameter('''pin''', '''654321''')
            }
        } 
        headers {
            header('''Accept''', '''application/json''')
            header('''Content-Type''', '''application/json;charset=UTF-8''')
        }
    }
    response {
        status 200
        body('''{"result":"Your PlN is apnalnd"}''')
        headers {
            header('''Content-Type''', '''application/json''')
        }
    }
}

verify_pin.json与verify_pin_fail.json是verify_pin_fail.groovy与verify_pin.groovy目标文件,也是真正起作用的文件。 verify_pin.json

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "id" : "a8c7b023-e2dc-4105-956c-f6b46e65d447",
  "request" : {
    "urlPath" : "/verify_pin/1111222233",
    "method" : "GET",
    "headers" : {
      "Content-Type" : {
        "equalTo" : "application/json;charset=UTF-8"
      },
      "Accept" : {
        "equalTo" : "application/json"
      }
    },
    "queryParameters" : {
      "pin" : {
        "equalTo" : "123456"
      }
    }
  },
  "response" : {
    "status" : 200,
    "body" : "{\"result\":\"OK\"}",
    "headers" : {
      "Content-Type" : "application/json"
    }
  },
  "uuid" : "a8c7b023-e2dc-4105-956c-f6b46e65d447"
}

verify_pin_fail.json

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
{
  "id" : "ccf996bb-0388-4a3b-83d7-d2891a303c80",
  "request" : {
    "urlPath" : "/verify_pin/1111222233",
    "method" : "GET",
    "headers" : {
      "Content-Type" : {
        "equalTo" : "application/json;charset=UTF-8"
      },
      "Accept" : {
        "equalTo" : "application/json"
      }
    },
    "queryParameters" : {
      "pin" : {
        "equalTo" : "654321"
      }
    }
  },
  "response" : {
    "status" : 200,
    "body" : "{\"result\":\"Your PlN is apnalnd\"}",
    "headers" : {
      "Content-Type" : "application/json"
    }
  },
  "uuid" : "ccf996bb-0388-4a3b-83d7-d2891a303c80"
}

将产生的verify_pin_fail.groovy与verify_pin.groovy契约文件(注意:不是verify_pin_fail.json与verify_pin.json)拷贝到src/test/resources/contracts下,运行mvn spring-cloud-contract:convert&&mvn spring-cloud-contract:run命令,当出现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Host: []
Content-Length: [538]
Content-Type: [text/plain; charset=UTF-8]
Connection: [keep-alive]
User-Agent: [Apache-HttpClient/5.1.3 (Java/17.0.10)]
{
  "id" : "16d3118b-27c6-48fb-b020-83dfd89ef7db",
  "request" : {
    "urlPath" : "/verify_pin/1111222233",
    "method" : "GET",
    "queryParameters" : {
      "pin" : {
        "equalTo" : "654321"
      }
    }
  },
  "response" : {
    "status" : 200,
    "body" : "{\"result\":\"Your PlN is apnalnd\"}",
    "headers" : {
      "Content-Type" : "application/json;charset=UTF-8"
    },
    "transformers" : [ "response-template", "spring-cloud-contract" ]
  },
  "uuid" : "16d3118b-27c6-48fb-b020-83dfd89ef7db"
}

[INFO] Started stub server for project [C:\Code\MyJava\javawork\card\target\stubs:+:stubs] on port 8080 with [2] mappings
[INFO] All stubs are now running RunningStubs [namesAndPorts={C:\Code\MyJava\javawork\card\target\stubs:+:stubs=8080}]
[INFO] Press ENTER to continue...

在浏览器中输入:http://127.0.0.1:8080/verify_pin/1111222233?pin=123456

输入:http://127.0.0.1:8080/verify_pin/1111222233?pin=654321

接下来将契约文件上传到GitHub中( 由于我没有GitHub Server,所以没有实现)。

第一次服务消费者从GitHub下载契约文件到本地,在target/generated-test-sources/contracts/org/springframework/cloud/contract/verifier/tests自动形成ContractVerifierTest.java文件。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package org.springframework.cloud.contract.verifier.tests;

import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;
import io.restassured.response.ResponseOptions;

import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat;
import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*;
import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;
import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;

@SuppressWarnings("rawtypes")
public class ContractVerifierTest {
  @Test
  public void validate_verify_pin() throws Exception {
    // given:
      MockMvcRequestSpecification request = given();
    // when:
      ResponseOptions response = given().spec(request)
          .queryParam("pin","123456")
          .get("/verify_pin/1111222233");

    // then:
      assertThat(response.statusCode()).isEqualTo(200);
      assertThat(response.header("Content-Type")).isEqualTo("application/json;charset=UTF-8");

    // and:
      DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
      assertThatJson(parsedJson).field("['result']").isEqualTo("OK");
  }

  @Test
  public void validate_verify_pin_fail() throws Exception {
    // given:
      MockMvcRequestSpecification request = given();

    // when:
      ResponseOptions response = given().spec(request)
          .queryParam("pin","654321")
          .get("/verify_pin/1111222233");

    // then:
      assertThat(response.statusCode()).isEqualTo(200);
      assertThat(response.header("Content-Type")).isEqualTo("application/json;charset=UTF-8");

    // and:
      DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
      assertThatJson(parsedJson).field("['result']").isEqualTo("Your PlN is apnalnd");
  }
}

启动本地服务,编写然后运行测试文件CardApplicationTests.java

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.web.client.RestTemplate;

@SpringBootTest
class CardApplicationTests {
  private RestTemplate restTemplate = new RestTemplate();
  @Test
  void pass() throws Exception{
    String result = restTemplate.getForObject("http://localhost:8080/verify_pin/1111222233?pin=123456", String.class);
    Assertions.assertEquals(result, "{\"result\":\"OK\"}");

  }
  
  @Test
  void fail() throws Exception{
    String result = restTemplate.getForObject("http://localhost:8080/verify_pin/1111222233?pin=654321", String.class);
    Assertions.assertEquals(result,"{\"result\":\"Your PlN is apnalnd\"}");
  }
}

保证测试通过

以后每次运行CardApplicationTests.java之前,都从GitHub上下载契约文件,启动本地服务。如果测试fail,说明接口发生了变化,通过团队线下解决。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Spring Boot+cucumber+契约测试
1.使用start.spring.io创建一个“web”项目。在“依赖项”对话框中搜索并添加“web”依赖项,为了后面的契约文件,再加入“Config Client ”和“Contract Stub Runner依赖项。点击“生成”按钮,下载zip,并将其解压缩到计算机上的文件夹中。
顾翔
2024/09/10
1180
Spring Boot+cucumber+契约测试
微服务架构与springcloud03——项目热部署与消费者订单模块
自动热部署会消耗一定的性能,如果您的电脑配置不佳,可能会有点卡顿。除了自动热部署,也可以通过手动按下面的锤子按钮,只编译修改的文件,会比重启更加快点。
半旧518
2022/10/26
3350
微服务架构与springcloud03——项目热部署与消费者订单模块
Spring Boot+cucumber
1 使用start.spring.io创建一个“web”项目。在“依赖项”对话框中搜索并添加“web”依赖项,如屏幕截图所示。点击“生成”按钮,下载zip,并将其解压缩到计算机上的文件夹中。
顾翔
2024/09/10
1250
Spring Boot+cucumber
第十六节 SCC消费驱动测试-生产端
[https://docs.spring.io/spring-cloud-contract]
用户1418372
2021/06/01
6210
第十七节 SCC消费驱动测试-消费端
[https://docs.spring.io/spring-cloud-contract]
用户1418372
2021/06/01
4810
Docker 部署 SpringCloud 微服务(docker-compose 编排微服务高可用案例)
前面的一篇文章,通过对每个项目建立单独的 Dockerfile,可以实现对单个项目生成 Docker 镜像,然后单独启动容器,可以实现简单连接,达到部署的目的。
子乾建建-Jeff
2020/06/29
9.4K2
Docker 部署 SpringCloud 微服务(docker-compose 编排微服务高可用案例)
SpringCloud 微服务实现方式 原
消费启动服务,注意EnableFeginClients 一定要加basePackages,要不然扫不到单独作为api的jar包里面接口
用户2603479
2018/08/15
4730
一文带你了解服务降级的前世今生
  在分布式的环境下,多个服务之间的调用难免会出现异常、超时等问题,这些问题出现的时候,为了提高用户的体验,我们不能够直接将错误的信息展示给用户,而是在出现这种情况的时候,给用户返回一个友好的提示。服务降级的作用就在这里体现了。
IT学习日记
2022/09/13
5670
一文带你了解服务降级的前世今生
微服务(五)——服务注册与发现:Zookeeper&Consul
6.启动8004注册进zookeeper(要先启动zookeeper的server)
不愿意做鱼的小鲸鱼
2022/09/26
3670
微服务(五)——服务注册与发现:Zookeeper&Consul
微服务(十二)——Steam消息驱动&Sleuth链路监控
有没有一种新的技术诞生,让我们不再关注具体MQ的细节,我们只需要用一种适配绑定的方式,自动的给我们在各种MQ内切换。(类似于Hibernate)
不愿意做鱼的小鲸鱼
2022/09/26
4320
微服务(十二)——Steam消息驱动&Sleuth链路监控
Spring Cloud构建微服务架构:服务消费者
通过上一篇《Spring Cloud构建微服务架构:服务注册与发现》,我们已经成功地将服务提供者:compute-service服务注册到Eureka服务注册中心或Consul服务端上了,那么我们要如何去消费服务提供者的接口呢? Spring Cloud Ribbon Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具。它是一个基于HTTP和TCP的客户端负载均衡器。它可以通过在客户端中配置ribbonServerList来设置服务端列表去轮询访问以达到均
程序猿DD
2018/02/01
8330
Zipkin和微服务链路跟踪
本期分享的内容是有关zipkin和分布式跟踪的内容。 首先,我们还是通过spring initializr来新建三个项目。一个zipkin service。另外两个是普通的业务应用,分别叫servic
ImportSource
2018/04/03
7.9K1
Zipkin和微服务链路跟踪
微服务架构与springcloud04——Eureka服务注册与发现
如果你有自己的私人医生,那么你需要时直接与医生进行联系就可以。但大多数人都需要去医院,医院有很多病人,也有很多医生,那么就需要一个窗口来挂号、取号、管理余号等等。同样的道理,当我们的服务数量变得多起来,就需要进行服务注册与发现的管理了。
半旧518
2022/10/26
2250
微服务架构与springcloud04——Eureka服务注册与发现
Docker 部署 SpringCloud 微服务的服务提供者和消费者(初级版)
Spring Cloud 微服务和 Docker 容器化技术,随便拿出来一个,都够你玩半天喝二两的。那么当它俩交叉在一起时,确实让新手烧脑。
子乾建建-Jeff
2020/06/29
1.4K0
Docker 部署 SpringCloud 微服务的服务提供者和消费者(初级版)
微服务注册中心:Consul——服务注册
微服务注册中心:Consul——概念与基础操作介绍了consul的安装和基本操作,本篇开始在consul上进行服务注册与发现,语言使用Java,框架使用Spring Boot整合Consul。
程序员架构进阶
2021/05/27
2.5K0
微服务注册中心:Consul——服务注册
微服务注册中心:Consul——服务发现
说完了Consul的服务注册,那么就该到服务发现了。大家有过rpc框架使用经验的,例如nacos、eureka、dubbo等,就会了解服务中的角色,也就是生产者和消费者,也可以理解为服务的提供方和服务使用方。服务注册,是服务提供方把自己的信息(ip、端口、方法、参数&返回值信息)注册到一个中心;服务发现就是服务使用方,从中心获取到可用的服务提供方信息,并像本地方法调用一样调用其方法(远程方法),这也就是RPC(远程方法调用)的过程。
程序员架构进阶
2021/05/29
2K0
SpringCloud微服务框架搭建
一、微服务架构 1.1什么是分布式 不同模块部署在不同服务器上 作用:分布式解决网站高并发带来问题 1.2什么是集群 多台服务器部署相同应用构成一个集群 作用:通过负载均衡设备共同对外提供服务 1.3什么是RPC RPC 的全称是 Remote Procedure Call 是一种进程间通信方式。 它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即无论是调用本地接口/服务的还是远程的接口/服务,本质上编写的调用代码基本相同。 比如两台服务器
编程软文
2018/06/20
1.6K0
微服务综合案例-03-其他服务的创建
  上篇文章我们详细的介绍了product服务的创建,因为其他几个服务的创建过程是相似的,所以其他几个服务我们就快速创建了。
用户4919348
2019/06/17
4930
一文带你搞懂微服务的协调者SpringCloud
从零开始构建一套完整的分布式系统是困难的。在1.2节中,我们讨论了众多的分布式系统的架构,可以说每种架构都有其优势及局限,采用何种架构风格要看应用程序当前的使用场景。就微服务架构的风格而言,一套完整的微服务架构系统往往需要考虑以下挑战。
愿天堂没有BUG
2022/10/28
5100
一文带你搞懂微服务的协调者SpringCloud
微服务(八)——Hystrix服务降级、熔断、限流(上)
复杂分布式体系结构中的应用程序有数十个依赖关系,每个依赖关系在某些时候将不可避免地失败。
不愿意做鱼的小鲸鱼
2022/09/26
5820
微服务(八)——Hystrix服务降级、熔断、限流(上)
推荐阅读
相关推荐
Spring Boot+cucumber+契约测试
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验