Service Weaver:Google开源基于分布式应用程序开发的框架,重新定义微服务边界

大家好,我是萧楚河,公众号:golang面试经典讲解,感谢关注,一起学习一起成长。

一、前言

今年6月,一群谷歌员工(由谷歌软件工程师Michael Whittaker领导)发表了一篇名为“Towards Modern Development of Cloud Applications”的论文。

正如Whittaker等人所指出的,从架构上讲,微服务本身设置就有问题,它是一个没有边界的结构它们将逻辑边界(如何编写代码)与物理边界(如何部署代码)混为一谈。这就是问题的开始。

因此,谷歌的工程师们提出了一种堪称“微服务2.0”的方法。将应用程序构建为逻辑整体,但将其交给自动化运行时,后者可以根据应用程序所需的内容和可用的内容来决定在哪里运行工作负载。

基于新提出的结构,他们能够将系统的延迟降低15倍,成本降低9倍。

“从有组织的模块化代码开始,我们就可以将部署架构作为实现细节,”Google开发人员倡导者Kelsey Hightower在10月份对这项工作表示了下一步计划。

鉴于以上实践,诞生了Service Weaver。

1.1 什么是Service Weaver

ServiceWeaver是一个用于编写、部署和管理分布式应用程序的编程框架。您可以在机器上本地运行、测试和调试Service Weaver应用程序,然后使用单个命令将该应用程序部署到云中。

Service Weaver应用程序由许多组件组成。组件被呈现为常规Go接口,组件之间通过调用这些接口定义的方法来相互交互。这使得编写Service Weaver应用程序变得容易。你不需要编写任何联网或序列化代码,你只要写Go。Service Weaver还提供用于日志记录、度量、跟踪、路由、测试等的库。

1.2 什么是模块单体应用?

对于不熟悉的人来说,模块化单体应用是一种体系结构,其中整个应用程序都写成一个单独的应用程序,在一个单一的代码库中。模块化方面意味着单体应用被分成单独的组件,并且在不同组件之间有干净明确的接口。

这里是一个例子:
在这里插入图片描述

在这个单体应用中,有三个组件:订单、支付和运输。每个组件实现单体应用的一个特定部分,关键在于每个组件的大部分都是私有的,并且组件之间的任何通信都是通过明确定义的接口进行的。

这使得每个组件的内部可以进行更改和更新,而不会影响任何其他组件,假设接口未更改或破坏。

当多个团队在单体应用上工作时,这确实有助于在团队之间设定明确的边界,并使每个组件独立于其他任何组件发展,同时在组件之间显示明确的依赖关系。

每当你的单体应用被部署时,它都被部署为一个单一的应用程序,每个单体应用的实例都运行一个单一的进程。例如,如果你要部署到AWS,每个单体应用的实例都将作为一个进程运行在EC2实例上。

二、Service Weaver工作原理

2.1 与模块化单体应用区别

Service Weaver和传统的模块化单体应用之间的区别在于部署方式。使用Service Weaver构建的应用程序在部署时,不是将所有组件运行在同一台机器上的一个大进程。

在这里插入图片描述
相反,每个组件都作为一个独立的微服务进行部署。这非常巧妙,因为您既可以获得将所有代码放在单个代码库中并进行方便的本地开发的好处,又可以获得运行分布式架构的好处,其中您可以根据需要缩放每个组件,例如内存,CPU和实例数量等。

2.2 如何工作的?

ServiceWeaver的核心抽象是组件。组件就像一个参与者,ServiceWeaver应用程序是作为一组组件来实现的。具体地说,组件用一个常规Go接口表示,组件通过调用这些接口定义的方法来相互交互。

2.2.1 单组件

在本节中,我们将定义一个简单的hello组件,它只打印一个字符串并返回。首先,运行go mod init hello来创建一个go模块。

mkdir hello/
cd hello/
go mod init hello然后,创建一个名为main.go的文件,其中包含以下内容:

package main

import (
“context”
“fmt”
“log”

"github.com/ServiceWeaver/weaver"

)

func main() {
if err := weaver.Run(context.Background(), serve); err != nil {
log.Fatal(err)
}
}

// app is the main component of the application. weaver.Run creates
// it and passes it to serve.
type app struct{
weaver.Implements[weaver.Main]
}

// serve is called by weaver.Run and contains the body of the application.
func serve(context.Context, *app) error {
fmt.Println(“Hello”)
return nil
}

在构建和运行应用程序之前,我们需要运行ServiceWeaver的代码生成器,称为weavergenerate。weavergenerate编写一个weaver_gen.go文件,其中包含ServiceWeaver运行时所需的代码。我们将详细说明weaver generate到底做了什么,以及为什么我们稍后需要运行它。最后,运行应用程序!

$ go mod tidy
$ weaver generate .
$ go run .
Hello

2.2.2 多组件

在ServiceWeaver应用程序中,任何组件都可以调用任何其他组件。为了演示这一点,我们引入了第二个Reverser组件。创建一个文件Reverser.go。转到以下内容:

package mainimport ("context""github.com/ServiceWeaver/weaver"
)// Reverser component.
type Reverser interface {Reverse(context.Context, string) (string, error)
}// Implementation of the Reverser component.
type reverser struct{weaver.Implements[Reverser]
}func (r *reverser) Reverse(_ context.Context, s string) (string, error) {runes := []rune(s)n := len(runes)for i := 0; i < n/2; i++ {runes[i], runes[n-i-1] = runes[n-i-1], runes[i]}return string(runes), nil
}

Reverser组件由Reverse接口表示,该接口具有反转字符串的Reverse方法。reverser结构是我们对reverser组件的实现(如weaver.Implements[Reverser]所示它包含的字段)。

接下来,在main.go中编辑应用程序组件以使用reverser组件:


package mainimport ("context""fmt""log""github.com/ServiceWeaver/weaver"
)func main() {if err := weaver.Run(context.Background(), serve); err != nil {log.Fatal(err)}
}type app struct{weaver.Implements[weaver.Main]reverser weaver.Ref[Reverser]hello    weaver.Listener
}func serve(ctx context.Context, app *app) error {// Call the Reverse method.// The hello listener will listen on a random port chosen by the operating// system. This behavior can be changed in the config file.fmt.Printf("hello listener available on %v\n", app.hello)// Serve the /hello endpoint.http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {name := r.URL.Query().Get("name")if name == "" {name = "World"}reversed, err := app.reverser.Get().Reverse(ctx, name)if err != nil {http.Error(w, err.Error(), http.StatusInternalServerError)return}fmt.Fprintf(w, "Hello, %s!\n", reversed)})return http.Serve(app.hello, nil)
}

应用程序结构有一个类型为weaver.Ref[Reverser]的新字段,提供对反向器组件的访问权限。

2.2.3 多进程执行

我们已经了解了如何通过go run在单个流程中运行Service Weaver应用程序。现在,我们将在多个进程中运行我们的应用程序,在作为RPC执行的组件之间进行方法调用。首先,创建一个名为weaver.toml的TOML配置文件,其中包含以下内容:

[serviceweaver]
binary = "./hello"[multi]
listeners.hello = {address = "localhost:12345"}

此配置文件指定ServiceWeaver应用程序的二进制文件,以及hello侦听器的固定地址。接下来,使用weaver multi-deploy构建并运行应用程序:

go build                        # build the ./hello binary
weaver multi deploy weaver.toml # deploy the application

2.3 微服务如何组合?

我发现图表有助于理解的一个例子,这是Google解释了这些不同部分如何组合在一起的图表:

在这里插入图片描述
我们还没有谈到 Service Weaver 框架的多功能性。传统微服务的一个缺点是,你经常会遇到接口过于频繁的问题。毕竟,没有人能预见架构的演变方向。

然后,你不得不忍受增加的延迟和更高的网络调用失败率,或者花时间将这两个微服务合并起来。

使用 Service Weaver,这个问题得到了解决。如果你查看上面的图表,你会发现有四个模块被定义了。当部署为微服务时,你会注意到 A 和 B 住在一起,C 和 D 是他们自己的微服务。

使用 Service Weaver,你可以自由地定义组件在哪里部署。你可以选择让多个组件一起运行在单个微服务中,或者将所有组件都部署为单独的微服务。如果你的应用程序演变到两个组件变得过于频繁,并且作为单独的微服务运行,你可以轻松地将它们合并,而不需要改变代码,并在 Service Weaver 中快速更改配置。

三、Service Weaver使用

这里基于我的理解对Service Weaver的初步介绍,鉴于很多人可能希望自己实践一下,可以通过如下地址进入官方网站进行学习:https://serviceweaver.dev

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

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

相关文章

PyTorch基础操作

一、Tensor 在 PyTorch 中&#xff0c;张量&#xff08;Tensor&#xff09;是一个核心概念&#xff0c;它是一个用于存储和操作数据的多维数组&#xff0c;类似于 NumPy 的 ndarray&#xff0c;但与此同时&#xff0c;它也支持 GPU 加速&#xff0c;这使得在大规模数据上进行科…

vue简单实现滚动条

背景&#xff1a;产品提了一个需求在一个详情页&#xff0c;一个form表单元素太多了&#xff0c;需要滚动到最下面才能点击提交按钮&#xff0c;很不方便。他的方案是&#xff0c;加一个滚动条&#xff0c;这样可以直接拉到最下面。 优化&#xff1a;1、支持滚动条&#xff0c;…

吉林大学19、21级计算机学院《计算机网络》期末真题试题

一、21级&#xff08;考后回忆&#xff09; 一、不定项选择&#xff08;一共10个选择题&#xff0c;一个两分&#xff0c;选全得满分&#xff09; 不定项&#xff1a;可以选择1~4个 考点有&#xff1a; ①协议、服务 ②码分多路复用通过接受码片序列&#xff0c;求哪个站点发送…

Java反射篇----第三篇

系列文章目录 文章目录 系列文章目录前言一、反射使用步骤(获取 Class 对象、调用对象方法)二、获取 Class 对象有几种方法三、利用反射动态创建对象实例前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章…

分布式协调系统

分布式协调系统 分布式协调系统解决的进程间的通信和协作&#xff0c;根据是否在同一时间和是否相互引用分为四个模型。 示例系统Chubby 主功能&#xff1a;让客户端实现同步&#xff0c;方法是加锁服务 介绍一下系统&#xff1a; 系统由五台服务器构成&#xff0c;通过pax…

STM32通用定时器-输入捕获-脉冲计数

一、知识点 编码器   两相编码器&#xff08;正交编码器&#xff09;&#xff1a;两相编码器由 A 相和 B 相组成&#xff0c;相位差为 90 度。当旋转方向为顺时针时&#xff0c;A 相先变化&#xff0c;然后 B 相变化&#xff1b;当旋转方向为逆时针时&#xff0c;B 相先变化…

【leetcode】字符串中的第一个唯一字符

题目描述 给定一个字符串 s &#xff0c;找到 它的第一个不重复的字符&#xff0c;并返回它的索引 。如果不存在&#xff0c;则返回 -1 。 用例 示例 1&#xff1a; 输入: s “leetcode” 输出: 0 示例 2: 输入: s “loveleetcode” 输出: 2 示例 3: 输入: s “aabb”…

扩展 apiserver 连接认证 ip, apiserver证书更新

本文来自我的博客地址 文章目录 问题场景:问题分析:问题解决:查看 apiserver 证书支持的 ip 或 host使用 openssl 生成证书:再次查看 apiserver 证书支持的 ip 或 host 再次尝试将 master 加点加入参考 问题场景: k8s 1.28.1 集群后期新增 vip apiserver 证书不支持 vip 引入…

谈谈AI产品经理的产品开发流程

本文以智能文档审阅系统&#xff08;IDP&#xff09;和工业互联网数字孪生—故障预测为例&#xff0c;介绍AI产品经理在产品开发全流程过程中&#xff0c;每一阶段的工作内容、工作流程及注意事项&#xff0c;并结合具体案例方便对AI产品经理感兴趣的同学予以了解。文中尽量避免…

cpufreq子系统

cpufreq是linux上负责实现动态调频的关键&#xff0c;这篇笔记总结了linux内核cpufreq子系统的关键实现&#xff08;Linux 3.18.140&#xff09;。 概述 借用一张网络上的图片来看cpufreq子系统的整体结构&#xff1a; 用户态接口&#xff1a;cpufreq通过sysfs向用户态暴露接…

添加jdk 11到环境变量的一种方法

添加jdk 11到环境变量的一种方法 1.jdk11可以直接在android studio 中下载&#xff0c; File --> Settings --> Build, Execution, Deployment --> Build Tools --> Gradle 下载jdk 11 &#xff0c;确认好下载路径 2.jdk11 添加到环境变量添加到环境变量 多个…

java基于ssm的房源管理系统+vue论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…