写点什么

本地服务调用 K8S 环境中的 SpringCloud 微服务实战

作者:程序员欣宸
  • 2022 年 9 月 22 日
    广东
  • 本文字数:2878 字

    阅读完需:约 9 分钟

本地服务调用K8S环境中的SpringCloud微服务实战

欢迎访问我的 GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos


  • 下图是典型的微服务在 Kubernetes 环境的部署情况(简化版):


  • 在开发阶段,如果服务 B 还在开发中,部署情况如下图所示:


  • 此时的服务 B 如何才能访问到注册中心和服务 A 呢?

常规手段:通过 service 访问对应的 pod

  • 通常情况下,从外部访问 kubernetes 内部 pod 服务的方法是创建 service,再通过访问 service 的方式来访问对应的 Pod,但是这样做会变更 kubernetes 环境现有配置,例如原本注册中心对应的 service type 是 ClusterIP,这里只有改成 NodePort 或者 LoadBalancer 才能让外部访问到,又例如服务 A 原本没有 service,这里为了外部访问只能为其创建 service。

  • 如果这个 Kubernetes 环境是生产环境,上述改动都是不允许的,如果是开发环境,又会造成开发和生产环境有大量不一样的配置,因此,创建 service 虽然可行但并不是好方案。

更适合本地开发的方案:kubefwd 服务

  • 比 service 更适合本地开发的方案是使用 kubectl port-forward 命令在本地电脑创建 kubefwd 服务,例如将对当前电脑 8081 端口的请求,可以 kubefwd 转发到 kubernetes 上的注册中心 Pod 的 8080 端口;

  • 有了 kubefwd,我们在开发服务 B 的时候,只要把发往注册中心和服务 A 的请求都 kubefwd 服务转发到 kubernetes 上去就可以了,如下图:


  • 理论分析就到此吧,接下来一起实战本地服务调用 K8S 环境中的微服务。

实战环境

  • 以下是本次实战所需的环境,请确保您的 kubernetes 是正常可用的:


  1. kubernetes:

  2. kubectl:1.7.0

  3. kubernetes 所在 Linux 服务器:CentOS7.4

  4. 本地环境:win10 专业版 64 位

  5. SpringCloud:Edgware.SR1




源码下载

  • 本次实战的注册中心(eureka-server)、服务 A(service-provider)、服务 B(service-consumer)都在 GitHub 提供了对应的源码,地址和链接信息如下表所示:



  • 这个 git 项目中有多个文件夹,本章源码在 springcloudscaledemo 这个文件夹下,如下图红框所示:

实战

  • 本次实战的步骤是将注册中心和服务 A 部署到 kubernetes 环境,然后在本地运行服务 B,看服务 B 能否正常注册和调用服务 A。

  • 注册中心、服务 A、服务 B 与源码工程的对应关系如下:



  • 注意:以下的操作都在本地的 windows 电脑上完成

  • 创建注册中心的 deployment,执行以下命令:


kubectl run my-eureka --image=bolingcavalry/eureka-server:0.0.1-SNAPSHOT --replicas=1
复制代码


  • 创建名为 eurekahost 的服务,对应的 pod 是刚刚创建的 my-eureka:


kubectl expose deployment my-eureka --name=eurekahost --port=8080
复制代码


  • 创建服务 A 的 deployment:


kubectl run my-provider --image=bolingcavalry/service-provider:0.0.1-SNAPSHOT --replicas=1
复制代码


  • 查看 pod 的名字:


c:\software\kubectl>kubectl get podsNAME                           READY     STATUS    RESTARTS   AGEmy-eureka-7f958f96b7-drgt6     1/1       Running   0          25mmy-provider-78dcc87bcc-s7cvq   1/1       Running   0          19m
复制代码


  • 我这里注册中心 pod 名字是 my-eureka-7f958f96b7-drgt6,服务 A 的 pod 名字是 my-provider-78dcc87bcc-s7cvq

  • 通过 kubefwd 服务将本地 8081 端口的请求转发到 my-eureka-7f958f96b7-drgt6 的 8080 端口:


kubectl port-forward my-eureka-7f958f96b7-drgt6 8081:8080
复制代码


  • 此时用浏览器访问本机的 8081 端口,就能访问到注册中心了,如下图:



  • 通过 kubefwd 服务将本地 8082 端口的请求转发到 my-provider-78dcc87bcc-s7cvq 的 8080 端口:


kubectl port-forward my-provider-78dcc87bcc-s7cvq 8082:8080
复制代码


  • 此时用浏览器访问本机的 8082 端口,就能调用服务 A 的 http 接口了,地址是:http://localhost:8082/getuserinfo?id=101&name=Tom


  • 此时注册中心和服务 A 都可以在本地访问了,可以在本地开发服务 B 的代码了,详细源码请按照前面给出的地址下载,这里只贴出关键代码,首先是配置信息 application.yml,这是个普通的 SpringCloud 工程的配置,要注意的是 eureka 的地址和端口要改成 localhost:8081,这样请求才会被 kubefwd 服务转发到 kubernetes 上去:


server:  port: 8080spring:  application:    name: service-consumereureka:  client:    serviceUrl:      defaultZone: http://localhost:8081/eureka/  instance:    prefer-ip-address: true
复制代码


  • 服务 B 调用服务 A 用的是 FeignClient 的方式,在 FeignClient 的注解中,要用 url 参数指明服务 A 的地址是http://localhost:8082,这样对服务 A 的请求才会被转发到 kubernetes 上去:


@FeignClient(name = "microservice-provider-user", url = "http://localhost:8082")public interface UserFeignClient {
@RequestMapping(value = "/getuserinfo", method = RequestMethod.GET) String getUserInfoWithRequestParam(@RequestParam("id") String id, @RequestParam("name") String name);}
复制代码


  • 做一个 controller 类,接收到 web 请求后,就会调用服务 A 的 getuserinfo 接口,然后将服务 A 返回的内容加个前缀返回:


@RestControllerpublic class UserFacadeController {
@Autowired private UserFeignClient userFeignClient;
@GetMapping("/user/{id}/{name}") public String getUserInfo(@PathVariable("id") final String id, @PathVariable("name") final String name) { return "1. ---" + userFeignClient.getUserInfoWithRequestParam(id, name); }}
复制代码


  • 在本地运行此工程,去看注册中心页面,发现已经注册成功:


  • 在浏览器输入:http://localhost:8080/user/aaa/bbb ,可见服务 B 的返回内容中有调用服务 A 时返回的信息,所以调用成功:

    实战完成,从注册到远程调用都一切正常。

一点小遗憾

  • 在使用 kubectl port-forward 命令的时候,本来是想执行以下命令的,这样可以将本地请求转发到 my-eureka 的 deployment 上去,就不用指定具体的 pod 了(pod 的名字不如 deployment 固定):


kubectl port-forward deployment/my-eureka 8081:8080
复制代码


同样的困惑

  • 这里有一篇文章,文中作者也是在本地调用 kubernetes 服务时,同样是用 kubectl port-forward 解决了问题:https://imti.co/kubernetes-port-forwarding


  • 此文章的配图是比较细致清晰的,在此转载了:


  • 至此,本地服务调用 K8S 环境中的 SpringCloud 微服务实战已完成,当您开发微服务时如遇到类似场景,希望本文能够给您一些参考。

欢迎关注 InfoQ:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...


发布于: 2 小时前阅读数: 2
用户头像

搜索"程序员欣宸",一起畅游Java宇宙 2018.04.19 加入

前腾讯、前阿里员工,从事Java后台工作,对Docker和Kubernetes充满热爱,所有文章均为作者原创,个人Github:https://github.com/zq2599/blog_demos

评论

发布
暂无评论
本地服务调用K8S环境中的SpringCloud微服务实战_Kubernetes_程序员欣宸_InfoQ写作社区