Hello Service Mesh, Hi Istio, 这就是架构的力量吗

有些人很好,你很想爱上他,但就是做不到。有些人没那么好,可你就是没法不爱他

Service Mesh 他是谁 | 框架/设计理念

Service Mesh 并不是一个框架或一个协议,而是一种用于处理服务到服务通信的基础设施层。它通常作为一个独立的组件,将微服务架构中的服务与其它服务解耦,使得开发者可以专注于编写业务逻辑,而不必担心底层的通信细节。Service Mesh 的核心组件是代理(通常称为 sidecar 代理)和控制平面。

Service Mesh 主要解决了在微服务架构中出现的一些挑战,例如:

  1. 负载均衡:Service Mesh 可以根据不同的策略进行负载均衡,例如轮询、最少连接数等。
  2. 服务发现:Service Mesh 可以自动发现并注册新的服务实例,从而简化了服务的发现和配置。
  3. 安全通信:Service Mesh 可以提供基于 TLS/SSL 的安全通信,确保在服务之间传输的数据安全可靠。
  4. 故障注入与容错:Service Mesh 支持故障注入,以便在开发阶段模拟不同的故障场景。同时,它还提供了容错机制,如超时、重试和断路器等,帮助服务在发生故障时保持稳定。
  5. 监控与追踪:Service Mesh 可以收集关于服务之间通信的详细指标,以便进行性能监控和分析。此外,它还支持分布式追踪,方便开发者快速定位问题和分析系统行为。

有许多流行的 Service Mesh 实现,如 Istio、Linkerd 和 Consul Connect 等。它们提供了丰富的功能,以帮助开发者更好地管理和监控微服务架构。选择合适的 Service Mesh 取决于您的具体需求和团队的技术背景。

有许多流行的 Service Mesh 实现 不就说明其实Service Mesh是一个协议吗

Service Mesh 不是一个协议。它是一种用于处理服务到服务通信的基础设施层。我的表述可能让您误解了。流行的 Service Mesh 实现,如 Istio、Linkerd 和 Consul Connect 等,指的是采用了 Service Mesh 架构的一些具体产品或开源项目。

它们可能采用不同的协议来处理服务间通信,例如 HTTP/1.1、HTTP/2 或 gRPC 等。Service Mesh 本身并没有定义一个通用的协议。它关注的是将服务间通信的处理、监控和安全等问题从业务代码中解耦出来,以便更好地管理和监控分布式系统。

所以,Service Mesh 更像是一种设计理念或者说是一种架构模式,而不是一个协议。

Service Mesh架构组成 | 重在 sidecar 代理

Service Mesh 架构通常包括两个主要部分:数据平面和控制平面。数据平面主要负责服务间的通信,而控制平面则负责管理和配置数据平面。在 Service Mesh 架构中,每个服务实例都会部署一个 sidecar 代理(例如,Envoy 代理)。所有的服务间通信都会经过这些 sidecar 代理。

下面是一个 Service Mesh 应用的例子:

假设您有一个简单的电商应用,该应用由以下几个微服务组成:

  1. 订单服务(Order Service)
  2. 付款服务(Payment Service)
  3. 库存服务(Inventory Service)
  4. 用户服务(User Service)

在传统的微服务架构中,这些服务直接相互通信,需要在每个服务中处理诸如服务发现、负载均衡、安全通信等问题。这会导致大量重复代码和额外的复杂性。

引入 Service Mesh 后,您可以将这些通信问题的解决方案从服务代码中抽离出来。首先,为每个服务实例部署一个 sidecar 代理。然后,将服务间的所有通信都通过这些 sidecar 代理进行。这样,服务之间的通信逻辑就被独立出来了,开发者可以专注于实现业务功能。

在这个例子中,Service Mesh 的拓扑结构如下:

  1. 数据平面:包括与订单服务、付款服务、库存服务和用户服务相连的 sidecar 代理。
  2. 控制平面:一个独立的组件,负责管理和配置数据平面的 sidecar 代理。

控制平面可以根据您的需求进行配置,例如设置负载均衡策略、安全通信、超时和重试等。此外,Service Mesh 还提供了丰富的监控和追踪功能,方便您了解服务间通信的性能和行为。

通过使用 Service Mesh,您可以降低服务间通信的复杂性,提高系统的可维护性和可观测性。

Service Mesh | hello world

要在 Spring Boot 或 Spring Cloud 应用中使用 Service Mesh,您可以选择 Istio 作为 Service Mesh 实现,因为它与 Kubernetes 具有很好的集成,并且提供了与 Spring Cloud 应用相兼容的功能。下面是一个简化的示例,演示如何将 Istio 与 Spring Boot 和 Spring Cloud 结合使用。

  1. 准备环境

确保您已经安装了以下工具:

  • Kubernetes 集群(例如,使用 Minikube、k3s 或云提供商的 Kubernetes 服务)

  • kubectl(Kubernetes 命令行工具)

  • Istioctl(Istio 命令行工具)

  1. 安装 Istio

按照 Istio 的官方文档安装和配置 Istio。在安装过程中,启用自动注入 sidecar 代理的功能。这样,当您将 Spring Boot 应用部署到 Kubernetes 时,Istio 会自动为每个 Pod 注入 sidecar 代理(Envoy 代理)。

  1. 创建 Spring Boot 应用

创建一个简单的 Spring Boot 应用,例如使用 Spring Initializr。您可以选择 Web、Actuator 和其他您需要的依赖项。

  1. 编写代码

在您的 Spring Boot 应用中,编写一个简单的 REST 控制器,例如:

@RestController
public class MyController {
    @GetMapping("/hello")
    public String hello() {
        return "Hello from Service Mesh!";
    }
}
  1. 编写 Kubernetes 配置文件

创建一个名为 deployment.yaml 的 Kubernetes 配置文件,并配置您的 Spring Boot 应用。例如:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-spring-boot-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-spring-boot-app
  template:
    metadata:
      labels:
        app: my-spring-boot-app
    spec:
      containers:
      - name: my-spring-boot-app
        image: my-spring-boot-app:latest
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: my-spring-boot-app
spec:
  selector:
    app: my-spring-boot-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: LoadBalancer
  1. 构建和部署应用

使用 Docker 构建 Spring Boot 应用的镜像,并将其推送到 Docker Registry。然后,使用 kubectl 将应用部署到 Kubernetes 集群:

kubectl apply -f deployment.yaml
  1. 验证 Istio 已成功注入 sidecar 代理

使用以下命令验证 Istio 已经为您的 Spring Boot 应用的 Pod 注入了 sidecar 代理:

kubectl get pods

您应该看到一个包含两个容器的 Pod:您的 Spring Boot 应用容器和 Istio sidecar 代理(Envoy 代理)。

到此为止,您已经成功将 Istio Service Mesh 与 Spring Boot 和 Spring Cloud 应用集成。现在,您可以开始利用 Istio 提供的各种功能,如负载均衡、服务发现、安全通信、监控和追踪等。

下面是一个简单的例子,说明如何使用 Istio 进行负载均衡和超时设置:

  1. 创建一个 VirtualService 和 DestinationRule

创建一个名为 istio-config.yaml 的文件,然后添加以下内容:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-spring-boot-app
spec:
  hosts:
  - "*"
  http:
  - route:
    - destination:
        host: my-spring-boot-app
      weight: 100
    timeout: 3s
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: my-spring-boot-app
spec:
  host: my-spring-boot-app
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN

在这个例子中,我们为应用创建了一个 VirtualService,设置了超时时间为 3 秒,并创建了一个 DestinationRule,使用轮询(ROUND_ROBIN)策略进行负载均衡。

  1. 应用 Istio 配置

使用 kubectl 将 Istio 配置应用到 Kubernetes 集群:

kubectl apply -f istio-config.yaml

现在,Istio 会根据您的配置自动处理负载均衡和超时设置。您可以继续尝试 Istio 的其他功能,如安全通信、故障注入、监控和追踪等。

请注意,本示例只是简化版的实现,实际生产环境中可能会涉及更多的配置和细节。在实际项目中使用时,请参阅 Istio、Spring Boot 和 Spring Cloud 的官方文档以获取更多详细信息和最佳实践。

加入Istio后如何进行服务间调用的?

Istio 能够帮助管理服务间的调用,但它本身并不直接参与服务间的调用。服务间的调用仍然由您的应用代码发起,Istio 负责在 sidecar 代理层面处理通信的各种细节,例如负载均衡、故障注入、超时等。

下面是一个简单的示例,说明如何在两个 Spring Boot 应用之间进行服务调用,并在引入 Istio 后如何进行管理。

假设我们有两个服务:

  1. greeting-service:提供问候语。
  2. name-service:提供名字。

我们希望 greeting-service 能调用 name-service 以获取名字,并返回完整的问候语。

步骤 1:创建两个 Spring Boot 应用

创建两个简单的 Spring Boot 应用,分别为 greeting-servicename-service。您可以使用 Spring Initializr 来生成项目模板,并添加 Web 和 RestTemplate 依赖。

步骤 2:编写 name-service 代码

name-service 中编写一个简单的 REST 控制器,如下所示:

@RestController
public class NameController {
    @GetMapping("/name")
    public String getName() {
        return "John Doe";
    }
}

步骤 3:编写 greeting-service 代码

greeting-service 中编写一个 REST 控制器,如下所示:

@RestController
public class GreetingController {
    private final RestTemplate restTemplate;

    public GreetingController(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    @GetMapping("/greeting")
    public String getGreeting() {
        String name = restTemplate.getForObject("http://name-service/name", String.class);
        return "Hello, " + name + "!";
    }
}

请注意,我们使用 RestTemplate 发起对 name-service 的调用,其中 http://name-service/namename-service 的地址。

##### name-service 何来

当您使用 Service Mesh,如 Istio,进行服务间通信时,服务实际上会调用与其相连的 sidecar 代理(例如 Envoy 代理),而不是直接调用目标服务。在您的示例中,http://name-service/name 这个地址将被视为 name-service 的虚拟地址或服务名称,而不是原始服务或 sidecar 代理的 IP 地址。

当您使用 RestTemplate 发起对 name-service 的调用时,sidecar 代理会拦截该请求,根据 Service Mesh 的服务发现和负载均衡规则,将请求转发到目标服务的相应 sidecar 代理。目标 sidecar 代理再将请求转发到 name-service 实例。这种方式确保了服务间通信的透明性和解耦。

###### 这个服务地址 name-service 是在哪里配置的

在 Spring Cloud 应用程序中,服务地址(例如 name-service)通常是通过服务发现组件获取的。服务发现组件负责维护和提供服务的名称和实际地址信息。根据您使用的服务发现解决方案,配置方法可能会有所不同。

在 Spring Cloud 中,服务发现组件通常与 Spring Cloud Config Server 一起使用,后者提供了集中化的配置管理。这使得您可以在配置文件中定义服务地址,然后在服务发现组件中注册服务。当服务启动时,它会自动注册到服务发现组件,并获取其他服务的地址信息。

以下是一个简单的示例,说明如何在 Spring Cloud 中使用 Eureka 作为服务发现组件:

  1. application.ymlapplication.properties 配置文件中配置 Eureka 服务发现组件:
# application.yml  
eureka:  
  client:    serviceUrl:      defaultZone: http://localhost:8761/eureka/  instance:    preferIpAddress: true  
  1. 在 Spring Cloud 应用程序中使用 @EnableDiscoveryClient 注解启用服务发现功能:
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;  

@SpringBootApplication  
@EnableDiscoveryClient  
public class NameServiceApplication {  
    public static void main(String[] args) {        SpringApplication.run(NameServiceApplication.class, args);    }}  
  1. 在需要调用 name-service 的服务中,使用 RestTemplate 或其他 HTTP 客户端发起请求:
import org.springframework.cloud.client.loadbalancer.LoadBalanced;  
import org.springframework.web.client.RestTemplate;  

@Service  
public class NameServiceClient {  
    @Autowired    private RestTemplate restTemplate;  
    public String getName() {        return restTemplate.getForObject("http://name-service/name", String.class);    }  
    @Bean    @LoadBalanced    public RestTemplate restTemplate() {        return new RestTemplate();    }}  

在这个示例中,name-service 是在 Eureka 服务发现组件中注册的服务名称。RestTemplate 会自动使用服务名称解析服务实例的地址,然后发起请求。

当您使用 Service Mesh,例如 Istio,服务发现和负载均衡的功能将由 Service Mesh 的 sidecar 代理(如 Envoy)接管。在这种情况下,您只需将服务名称配置为虚拟服务地址,并在 Service Mesh 中定义相应的路由规则和目标服务实例。这样,sidecar 代理会根据 Service Mesh 的服务发现和负载均衡规则自动将请求路由到正确的目标服务实例。

###### name-service 是在 Eureka 服务发现组件中注册的服务名称, 如何在 eureka中配置这个 name-service

在 Spring Cloud 应用程序中,您不需要手动在 Eureka 中配置服务名称(如 name-service)。相反,服务名称是由应用程序在启动时自动注册到 Eureka 的。服务名称通常与应用程序的 spring.application.name 属性值相同。

假设您有一个名为 “name-service” 的服务,以下是如何配置和注册它的示例:

  1. name-service 应用程序的 application.ymlapplication.properties 配置文件中,设置 spring.application.name 和 Eureka 客户端配置:
# application.yml  
spring:  
  application:    name: name-service  
eureka:  
  client:    serviceUrl:      defaultZone: http://localhost:8761/eureka/  instance:    preferIpAddress: true  
  1. name-service 应用程序的主类中,使用 @EnableDiscoveryClient 注解启用服务发现功能:
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;  

@SpringBootApplication  
@EnableDiscoveryClient  
public class NameServiceApplication {  
    public static void main(String[] args) {        SpringApplication.run(NameServiceApplication.class, args);    }}  
  1. 启动 name-service 应用程序。应用程序将自动使用 spring.application.name 的值(在本例中为 “name-service”)作为服务名称,并将其注册到 Eureka。

现在,name-service 已注册到 Eureka,其他服务可以使用其服务名称发现和调用它。在其他服务中,您可以使用 RestTemplateFeignClient 等工具,通过服务名称(即 “name-service”)发起请求,而无需知道目标服务实例的具体 IP 地址和端口。

请注意,这个示例假设您已经正确配置并启动了 Eureka 服务注册中心。如果您还没有配置 Eureka 服务注册中心,请参考 Spring Cloud Eureka 文档 了解详细信息。

所以,在这个例子中,您可以将 http://name-service/name 看作是 name-service 的逻辑地址,而实际的通信将通过 sidecar 代理进行。您无需担心服务实例的具体 IP 地址,Service Mesh 会负责服务发现和负载均衡。

步骤 4:部署应用

按照之前的说明,为两个 Spring Boot 应用创建 Kubernetes 配置文件并部署它们。Istio 会自动为每个 Pod 注入 sidecar 代理(Envoy 代理)。

步骤 5:创建 Istio 配置

创建一个 Istio 配置文件(例如,istio-config.yaml),并为两个服务定义 VirtualService 和 DestinationRule。您可以根据需要配置负载均衡策略、超时等。

例如,您可以为 name-service 创建一个 VirtualService,使用 ROUND_ROBIN 策略进行负载均衡,并设置超时时间为 3 秒。

应用 Istio 配置:

kubectl apply -f istio-config.yaml

现在,当 greeting-service 调用 name-service 时,Istio 会自动处理负载均衡、超时等设置。服务间调用的流程与未使用 Istio 的情况相同,但通过引入 Istio,您可以在 sidecar 代理层面对这些通信细节进行集中管理,而无需修改应用代码。

Istio 的主要优势在于它将服务间通信的管理从应用代码中解耦出来,允许您在不修改代码的情况下调整通信策略。例如,您可以轻松地更改负载均衡策略、超时设置、故障注入等。

此外,Istio 还提供了丰富的监控和追踪功能,可以帮助您更好地了解服务间通信的性能和行为。通过使用 Istio,您可以降低服务间通信的复杂性,提高系统的可维护性和可观测性。

总结一下,引入 Istio 后,服务间调用的实现方式和原理并没有发生变化。应用代码仍然负责发起服务间调用,而 Istio 则在 sidecar 代理层面处理通信细节。这使得您可以在不修改代码的情况下管理和优化服务间通信,同时利用 Istio 提供的监控和追踪功能来提高系统的可维护性和可观测性。

采用 dubbo 进行调用, 那么我应该使用 Istio、Linkerd 和 Consul Connect哪一个框架好点呢?

在 Spring Cloud 中使用 Dubbo 作为 RPC 框架时,您可以考虑使用 Istio 作为 Service Mesh 解决方案。Istio 是一个功能丰富且成熟的 Service Mesh,支持多种协议,包括 HTTP/1.1、HTTP/2、gRPC 和 TCP。由于 Dubbo 使用 TCP 协议进行服务间通信,Istio 能很好地支持 Dubbo。

Istio 使用 Envoy 作为 sidecar 代理,可以有效地处理服务间通信,并提供诸如负载均衡、服务发现、流量控制、安全通信、监控和追踪等功能。这可以帮助您更好地管理和优化基于 Dubbo 的服务间通信,同时提高系统的可观测性和可维护性。

虽然 Linkerd 和 Consul Connect 也是很好的 Service Mesh 解决方案,但它们在处理非 HTTP 协议(例如 Dubbo 使用的 TCP 协议)时的支持相对较弱。因此,对于您的需求,Istio 作为 Service Mesh 框架可能是更合适的选择。然而,在做出决策时,还需要考虑您的具体需求和项目环境,以确保选择的方案符合您的期望。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值