微服务会把大的应用拆分成若干小的服务应用和前端应用,如何协调/治理这些应用,并解决在开发中遇到的各种问题是微服务面临的挑战。通常一个微服务系统需要关注的问题有:
为了解决上述问题,诞生了象 Spring Cloud 这样伟大的开发框架和系统。但这些能力都分布在各种 SDK 中,需要编写特定的代码进行操控,业务开发者需要理解整个框架,并熟悉周边的辅助系统。这些,无疑对开发者造成了困扰,提高了入门门槛。这个也造成了很多企业对于微服务改造的恐惧。
服务网格恰恰屏蔽了这些内容,将服务治理完全下沉到网络层。开发者无需再编写与业务无关的代码了。
“我只要写好 restful 的服务,丢到服务网格体系中,就 run 起来了,上面的那些能力自动获得。”
一个典型的服务网格应用示意如下图:
微服务通常由多个小组协同开发。在不了解服务网格的情况下,一般的企业技术决策者对于研发部门的能力考虑是单一技术栈,单一框架,考虑的出发点是技术栈可以保持延续,主要管理层可控(采用自己或心腹较擅长的技术)。并且如果企业大规模采用传统微服务开发,深入理解这些框架的大牛变得更加重要,一旦离开,后果便是灾难性的(如人人视频的 dubbo 大牛的离开)。
但在服务网格体系中,完全摆脱了技术栈和微服务框架的约束,允许开发者使用自己擅长的技术栈。企业决策者再也不必被某个核心技术人员掣肘,最难的服务治理问题已经被解决掉了。
服务网格对微服务的技术人员的要求和分工也带来了一些变化。通常的需求有两类:
当然,只要愿意,这两种角色可以合并,每个开发者都可以成为“技术大牛”。
但协调各个应用,仍然会需要约定,要求业务开发小组共同遵循。这些约定应该是适用所有微服务开发技术。
在服务网格中,服务端一般采用 http 的 restful 的方式。统一的响应格式会为开发带来便利,也易于封装统一的调用。
下面是一个典型的响应封装:
{
"service": "passport",
"timeStamp": 1559360704569,
"success": true,
"data": {
"items": [
{
"id": 1,
"title": "腾讯云",
}
],
"total": 1,
"limit": 20,
"offset": 0
}
}
当然,为了通信效率,我们在服务之间调用可以使用其他的二进制 rpc 协议。在 istio 体系中,默认支持了谷歌自家的 gRPC。通过对 envoy filter 的扩展,还会支持更多的 RPC 协议,如 thift,dubbo 等。
通常对于OO类的语言,会屏蔽接口格式和通信协议,把这些约定写入开发框架或者 SDK 中,远程调用就像本地调用一样(如 java 的 feign),这样的好处很明显。但缺点也很明显:你被框架/SDK 绑定了。
服务网格中,Restful 服务间的调用采用的是 协议 (http or https) + 内部服务名/域名 + 端口 调用,如:http://passport.xyz.svc.cluster.local:7301/{your_api_url} 。在这里的一个较好的实践是:在配置文件中使用短服务名映射,屏蔽 http 协议 和 端口,并在部署的时候将这个配置放到远程配置中心。如:
{
"passport":"https://passport.xyz:7301/"
}
在应用中:
//屏蔽协议,端口和域名
private String getRemote(String service, String url){
String uri = Util.getServiceUrl(service) + url;
return restTemplate.getForObject(uri, String.class);
}
//调用上述方法
String result = getRemote("passport", "/open/account/info?ticket=xxx");
这样就可以屏蔽由于部署导致的协议,端口,和域名的变更。
应用拆分的颗粒度问题:
服务的拆分没有一定的规则,不同的架构师/开发者会有不同的拆分方法。
服务暴露通常会带来安全的挑战。
通常建议最小暴露,按需暴露。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。