阅读更多

0顶
0踩

企业架构

转载新闻 创建微服务?请先回答这10个问题

2016-02-16 16:27 by 副主编 mengyidan1988 评论(0) 有5837人浏览
乍一看微服务似乎很容易构建,但是要真正构建微服务,要完成的工作可比在容器里运行一些代码,并在这些代码间使用HTTP请求进行通信,要多得多。在开发新的微服务之前——必须得在新服务部署到生产环境之前——你需要回答下面这10个重要的问题。
1. 如何测试服务?

当考虑到测试时,微服务有一些优势和劣势。一方面,定义良好的一小段功能的小型服务的单元测试,要比测试整个大型应用程序容易得多。另一方面,要验证由很多微服务组成的整个应用程序的质量,则必然会显著加大测试的复杂度:无法运行单个命令来测试一个进程里的代码,大量集成的互相依赖的组件必须首先运行起来,才能验证其健康状况,并且需要在测试过程中一直保持其运行。

新的微服务是否既会进行隔离测试(使用单元测试或模拟依赖),也会连接到一些生产环境里实际会连接的服务上,在更贴近实际使用情况的“集成”或者“过渡”环境里进行测试?测试是否会合并性能验证和错误模式?是否所有测试都会自动化,或者需要人为干预测试的运行以及测试结果的查看?要让微服务可以简单,快速,并且自动化地进行测试,这鼓励开发人员维护测试,并且避免“破窗”问题。

2. 如何配置服务?

一旦新的微服务部署到生产环境里,如何才能影响其内部行为?这里包括基础架构的改动(比如,在资源池里改变最小进程数),以及一些应用程序级别的改动(比如,通过触发特性标志来启动新特性)。对于这所有的改动,要重点注意让这些改动生效是否需要重启服务。

3. 系统的其他部分如何使用该服务?

除非系统的其他组件的确需要使用某个服务,才有必要构建它,因此理解它们会如何使用该服务至关重要。

其他组件和这个新服务的交互是同步还是异步的?是否鼓励它们缓存来自该服务的响应?怎样重试并且保证结果的幂等性?新的微服务的在线时间的SLA是否匹配系统的其他组件?

需要清晰定义这个新的微服务所能够提供的响应延迟,调用该服务的组件必须知道这些指标。这样,当没有达到这些指标时,系统的其他部分才能够决定发出超时信号,中断当前操作,或者转到服务的另一个实例上。

4. 如何保护该服务?

除非在一个要求高度安全的环境里,大部分部署在防火墙后的微服务不需要过多操心服务内的安全性。在微服务之间添加大量的安全检查会带来巨大的操作复杂度,并且使得生产环境问题更难调试和修复。即使为服务内通信使用HTTP之上的HTTPS都会因为要求维护,部署以及保护一些正确签名的证书,而带来大量维护上的额外开销。

通常的方案是让流量在微服务间畅行无阻,同时使用应用程序级别的授权和认证,这样来保证应用程序级别的安全。

因此,系统里的其他组件应该能够给微服务发送请求,但是可能仍然需要同时传递一些认证数据,这些数据代表实际被批准的该请求最初的外部用户。这些数据永远不能是明文密码数据,可以使用类似JWT,OAuth,SAML和Auth0这样的技术。不管使用哪种方案,都需要清晰记录所用技术,最好包含在客户端库或者示例代码里,从而让其他开发人员能够轻松使用这个新的微服务。

5. 如何发现服务?

当新的微服务启动后,系统里的其他组件如何发现它?发现服务的流程越简单,可能的复杂度就越小,但是之后面临的问题就会越多。比如,最简单的方法(当然也很容易出错)就是在其他依赖于该服务的组件代码或者配置里硬编码微服务的地址。这样确实能够工作,直到服务地址发生变动,或者直到在其他域里启动了该服务的多个实例。这显然不是推荐的方式。

使用间接技术,比如DNS名称,能够一定程度上更好地隐藏微服务的地址,但是这样的方案也有自身的缺陷:找到一个合适的TTL值,强制重做名称解析,保证DNS缓存行为一致,等等。从设计上看,DNS并没有考虑服务的可用性,这会使得应用程序的组件将请求发送到一个无人侦听的IP地址,会很浪费时间,并且因为尝试找到能够工作的实例而干扰到实际的运营。这也会让开发人员的体验非常糟糕,因为使用DNS作为路由机制通常会导致开发人员需要频繁修改其/etc/hosts文件。

最复杂的方案里,高可用的数据库和数据同步服务(比如ZooKeeper)可能会用作当前可用并且工作良好的微服务的注册处。这样的方案要求更多的技术投资,并且需要小心处理,保证发现服务本身不会成为单点故障点(Single Point of Failure,SPOF)。微服务启动时,会将自身注册到这样的注册服务里,微服务关闭时则会将自身移除。如果微服务意外终止或者死锁了,它们也会被自动地从注册处移除。记住,发现服务并不仅仅是找到什么在运行——知道什么不可用也非常重要。

6. 负载增加时服务如何扩展?

如果某个微服务在应用程序里的确很有价值,那么使用其的开发人员会不断增加,随着使用的增长,流量会激增。新的微服务有设计良好的扩展计划,这对于运营团队非常重要。

微服务是否能自动扩展?是否有状态驻留在内存里,导致自动扩展和请求路由很困难(比如,用户会话状态)?如果有的话,分区策略是什么?

如果能事先了解大幅扩展时微服务的哪个部分会首先出错会很有用。对于由数据库支持的服务而言,计算能力(比如,位于自动扩展组里的EC2实例)通常能够持续扩展直到数据库不堪重负。对于真正的无状态服务而言(比如,不从数据库读取也不写入的计算型微服务),首先会出问题的可能是位于实例集群之前的负载均衡器。这两种情况都有对应的解决方案,不过在部署微服务的第一个版本时,这些方案并不一定需要就位。但是,需要详细了解新的微服务的限制,这样才能在生产环境能力达到上限之前就知道服务扩展的天花板位于何处。

7.该服务如何处理其依赖错误?

即使微服务的范围非常小,它也可能依赖于系统里已有的其他服务或者monolith程序。比如,大部分应用程序事务需要查看客户信息,因此用来访问客户记录的服务通常是提供业务价值的大部分服务的依赖。
如果新的微服务依赖于任何其他服务,当这些依赖服务故障时会发生什么至关重要。使用固定的请求超时时间是个好的开始,但是添加流程断点可能会更好。所依赖服务的所有者应该也希望其使用者在故障发生时使用类似指数延迟的技术,来避免惊蛰问题的发生。

这种场景很好测试,因为其测试只需要所依赖服务不可用即可。但是,务必记住所依赖服务API的调用失败可能会有很多种原因,这些故障表现也各不相同。

8. 系统的其他部分如何处理该新服务的故障?

取决于在新微服务的高可用能力上投资多少,也取决于其支持何种事务,这可能并不是个重要的问题。比如,一个简单的运营日志微服务,通过UDP异步发送数据,可能出现几分钟的故障,但是这对于应用程序的主要业务事务并没有任何影响。但是,异步处理信用卡事务的微服务如果发生故障,则可能严重损坏电子商务系统,那么这种故障场景就必须严格测试,并为之做好应对准备。

因此,即使范围有限的微服务(或者其开发人员)不需要担心系统的其他部分如何使用这个新组件,系统级别上关于每个服务如何依赖于其他服务的考量能够帮助避免连锁故障,也能帮助确保应用程序的整体性能。

9. 该服务如何升级?

可能大家倾向于认为Docker这样的容器技术,和Ansible这样的部署自动化工具使得升级变得不那么重要,但是微服务的维护需要考虑很多这些已有工具无法解决的其他方面的问题。

定义升级策略,并且决定微服务支持的部署复杂度级别十分重要。想用新版本取代旧版本时,canary测试,蓝/绿部署,特性标志,以及response diff'ing这些,比起简单的滚动升级而言,要求更多的时间和投入。

为微服务API的升级定义界线和策略对于依赖于其的组件更为重要。比如,一次只允许某个API的JSON schema添加一个改动,这样使得服务能够持续改进,并且不要求其使用者每次都必须随之升级。但是,向XML响应负载里添加新字段时,如果其使用者每次都做XML schema验证的话就会导致严重的问题。因此如果规律升级新的微服务,向其API对象添加越来越多的字段,那么需要在其文档里清晰记录,告知其服务的使用者。

最后,要了解如果新版本有问题时,微服务如何回滚,以及如何考虑“回滚判断指标”。

10.如何监控并度量服务?

如果你的公司已经有了应用程序监控的标准,那么就应该使用这些标准,借助已有的监控生态系统。注意不能忽略已有标准——或者更为严重地——使用新的监控工具而运营团队之前完全没有使用过。

如果你的公司还没有高质量的应用程序监控系统,向应用程序添加新的微服务可以作为推动监控系统搭建的起点。这对于之前都是监控大型monolithic应用程序,现在才开始向微服务架构迁移的企业来说尤其重要:一系列互相连接的微服务的运营监控需求要比单个大型的monolith程序的监控需求复杂得多。

无论选择哪种监控方案,是自己开发,选择开源软件还是商业软件,微服务的开发人员都应用能够完全访问其组件的监控和度量数据。如果缺失这样的透明度,那么就无法实现完整的反馈回路,开发人员就无法知道如何在生产环境里改进其服务,也无法在发生问题时帮助快速诊断出问题所在。

总结

并不要求大家对上述10个问题的每一个都有特别详细的答案,但是需要对每点都加以考虑,并且知道微服务可能会带来的架构上的限制。比如,一开始新的微服务部署时可能并没有考虑灾备和域故障容忍,随后升级来包含这样的能力。了解微服务当前能做什么,不能做什么至关重要,思考上述问题的答案能够帮助持续改进服务,最终演进成为成熟的,弹性的,可靠的系统组件。

原文链接:Creating a Microservice? Answer these 10 Questions First
译文来自:http://dockone.io/(翻译:崔婧雯 校对:李颖杰)
来自: dockone.io
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • java socket 传送进度_java-★-Socket文件上传/进度条

    客户端代码:1、客户端运行程序:package wtb.khd;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.DataOutputStream;import java.io.File;import java.io.FileInputStream;import java.io...

  • Socket实现简单文件传输(TCP)

    3.调用socket.shutdownInput或socket.shutdownOutput后,inputStream或outputStream被禁用,但socket不会被关闭。1.调用socket.close后无需再关闭通过socket创建的inputSteam或outputStream。2.调用inputSteam.close或outputStream.close后,socket也会被关闭。

  • socket文件传输

    socket实现文件传输,很拉我就记录下

  • 使用Socket技术进行数据传输、传输文件;浏览器访问Socket服务器

    计算机网络基础 IP地址和端口 TCP和 UDP Socket技术 使用Socket进行数据传输 使用Socket传输文件 使用浏览器访问Socket服务器

  • 通过Socket实现文件上传/上传文件

    文章目录整个功能的实现步骤客户端的实现步骤服务端的实现步骤 整个功能的实现步骤 1.客户端使用本地的字节输入流读取被上传的文件数据 2.客户端使用网络字节输出流,将读取到的文件数据发送给服务端 3.服务端使用网络字节输入流读取客户端发送过来的文件数据 4.服务端使用本地字节输出流将读取到的文件数据写入到指定的服务器本地文件中(例如,保存到目录 upload 下面) 5.服务端使用网络字节输出流,给客户端回写一段文字:“上传成功” 6.客户端使用网络字节输入流,读取服务端返回的数据 7.释放资源 注意: 1.

  • 基于Java实现Socket文件传输代码详解

    当涉及到网络通信和数据传输时,Socket 是一个非常重要的概念。Socket 可以被看作是在不同设备之间进行通信的一种方式,它提供了一种简单而强大的机制,用于实现客户端和服务器之间的数据交换。在本博客中,我们将探讨 Socket 的基本原理和使用方法,并通过一个具体的示例来展示如何使用 Socket 进行文件传输。Socket 实战传输文件的代码将帮助你深入理解如何利用 Socket 在客户端和服务器之间传输文件。在这篇博客中,我们学习了一个基于 Socket 的文件传输示例。

  • C语言socket传输文件

    可以传输大型文件,其基本思想为把文件名字读出来放到filename数组中,然后copy到buffer中,接着将独到的文件内容接在buffer数组中文件名称后面。然后循环读取,以后每次将独到的数据放入buffer传输。TCP服务端和TCP客户端编程,完成文件传输(客户端输入文件名,服务端接收文件数据并保存至服务端本地)此文件是在Linux系统运行的,Windows中不包含socket等头文件。关于头文件可以参考socket编程中用到的头文件。关于用到的函数可以通过查询C 语言教程。下面是客户端端的代码。

  • 【python】socket-传输多个文件、大文件

    使用一个TCP连接发送多个文件、大文件

  • 计算机网络 socket方式传输文件

    socket通信实现文件的传输,TCP传输方式,python版与C/C++版。 python版 服务器端代码 TCPserver.py: # -*- coding:utf-8 -*- import socket import os import threading # 获取本机ip def get_host_ip(): try: s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(('8.8.

  • 用socket实现文件传输

    socket实现文件传输

  • 简单的Socket文件传输

    分别使用多线程和Select模型,留档等工作了再回头看看。写得又乱又差...但就目前而言能写出来就算成功。

  • 使用Socket套接字传输数据流程详解(面向过程)

    注意我们这里要创建一个新的int类型,取名就叫m_client(在服务端里,不会名字冲突),因为accept()会返回一个socket,这个socket其实就是客户端的socket m_client,所以我们在服务端里也直接取同名m_client。从这里开始,客户端和服务端的联系就开始紧密起来了,从现在开始m_server这个socket就不要了,我们之后的读和写就已经同一在一个地方了,就是m_client,后续的操作也都是对m_client的操作。第二个填请求队列最大长度,一般填5,10,20都行。

  • 使用Socket进行客户端文件传输到服务器端的编程实现

    首先,让我们来了解一下Socket编程是什么。Socket是一种用于网络通信的编程接口,它允许计算机上的程序通过网络发送和接收数据。在这个例子中,我们将使用Socket编程来实现客户端将文件传输到服务器端的功能。通过以上步骤和示例代码,您可以使用Socket编程实现客户端将文件传输到服务器端的功能。这种方式可以用于各种文件的传输,包括文本文件、图像、音视频等。在运行代码之前,请确保服务器端和客户端的IP地址和端口号匹配,并将要传输的文件路径正确设置。

  • 14.9 Socket 高效文件传输

    网络上的文件传输功能也是很有必要实现一下的,网络传输文件的过程通常分为客户端和服务器端两部分。客户端可以选择上传或下载文件,将文件分块并逐块发送到服务器,或者从服务器分块地接收文件。服务器端接收来自客户端的请求,根据请求类型执行对应的操作,并根据发送的文件名或其他标识来确定要传输的文件。

  • 22、socket编程实现文件传输功能

    这节我们来完成socket文件传输程序,这是一个非常实用的例子。要实现的功能为:client 从 server下载一个文件并保存到本地。 编写这个程序需要注意两个问题: (1)文件大小不确定,有可能比缓冲区大很多,调用一次 write()/send() 函数不能完成文件内容的发送。接收数据时也会遇到同样的情况。 要解决这个问题,可以使用 while 循环,例如: //server代码 ch...

  • C/C++用socket实现简单的TCP文件传输

    本文主要用于总结学习到的关于socket网络编程的知识以及回顾项目原理等相关内容,进一步加深了对于TCP通信与实际项目之间联系的理解,也欢迎各位大佬对于文章中的错误理解进行批评指正以及对进一步完善所需要学习了解的知识原理给出重要建议

  • 【网络编程学习记录10】socket编程实现文件传输功能_申明 本学习笔记是在该教程的基础上结合自己的学习情况进行的总结,不是原创,想要(1)

    注意 server.cpp 第42行代码,recv() 并没有接收到 client 端的数据,当 client 端调用 closesocket() 后,server 端会收到FIN包,recv() 就会返回,后面的代码继续执行。//文件读取完毕,断开输出流,向客户端发送FIN包。#pragma comment (lib, “ws2_32.lib”) //加载 ws2_32.dll。//阻塞,等待客户端接收完毕。//文件接收完毕后直接关闭套接字,无需调用shutdown()//循环发送数据,直到文件结尾。

  • C#基于Socket的局域网即时通信和传输文件程序

    只要挂个阿里云,把IP地址和端口改一下,也可以实现内网穿透了。利用了Socket搭建了一个服务端和客户端,两个端之间可以通信。虽然很稚嫩,但是是当时的心血之作,那就放上来博客了。

  • linux tcp实现文件传输,socket-基于TCP连接实现文件内容传输

    #include #define SERVPORT 5555 //服务器监听窗口#define BACKLOG 10 //请求队列的长度数#define BUFFSIZE 1024int main(int argc,char *argv[]){int ret = 0;int flag = 0;int socketfd = 0;int filefd = 0;struct sockadd...

  • Socket实现文件传输

    Socket实现文件传输 1.客户端 通过new Socket("ip",port)连接服务端 创建文件输入流读取文件 创建返回套接字的输出流 写入文章名称,长度等属性 读取、写入文章操作 关闭流 package com.company; import javax.xml.crypto.Data; import java.io.*; import java.net.Socket...

Global site tag (gtag.js) - Google Analytics