10

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

 1 year ago
source link: https://blog.51cto.com/zq2599/5701937
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

欢迎访问我的GitHub

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

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

    本地服务调用K8S环境中的SpringCloud微服务实战_kubernetes
  • 在开发阶段,如果服务B还在开发中,部署情况如下图所示:

    本地服务调用K8S环境中的SpringCloud微服务实战_kubernetes_02
  • 此时的服务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环境中的SpringCloud微服务实战_kubernetes_03
  • 理论分析就到此吧,接下来一起实战本地服务调用K8S环境中的微服务。

  • 以下是本次实战所需的环境,请确保您的kubernetes是正常可用的:
  1. kubernetes:
  2. kubectl:1.7.0
  3. kubernetes所在Linux服务器:CentOS7.4
  4. 本地环境:win10专业版64位
  5. SpringCloud:Edgware.SR1
镜像名 角色 镜像对应的源码
bolingcavalry/eureka-server:0.0.1-SNAPSHOT 注册中心 eureka-server工程
bolingcavalry/service-provider:0.0.1-SNAPSHOT 服务A,提供http服务 service-provider工程
  • 本次实战的注册中心(eureka-server)、服务A(service-provider)、服务B(service-consumer)都在GitHub提供了对应的源码,地址和链接信息如下表所示:
名称 链接 备注
项目主页  https://github.com/zq2599/blog_demos 该项目在GitHub上的主页
git仓库地址(https)  https://github.com/zq2599/blog_demos.git 该项目源码的仓库地址,https协议
git仓库地址(ssh)  [email protected]:zq2599/blog_demos.git 该项目源码的仓库地址,ssh协议
  • 这个git项目中有多个文件夹,本章源码在springcloudscaledemo这个文件夹下,如下图红框所示:
    本地服务调用K8S环境中的SpringCloud微服务实战_kubernetes_04
  • 本次实战的步骤是将注册中心和服务A部署到kubernetes环境,然后在本地运行服务B,看服务B能否正常注册和调用服务A。<br>

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

角色 源码工程 备注
注册中心 eureka-server eureka注册中心服务,部署在kubernetes
服务A service-provider springboot工程,部署在kubernetes,在eureka注册,提供http接口getuserinfo
服务B service-consumer springboot工程,部署在本地windows电脑上,提供http接口user
  • 注意:以下的操作都在本地的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 pods
NAME                           READY     STATUS    RESTARTS   AGE
my-eureka-7f958f96b7-drgt6     1/1       Running   0          25m
my-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端口,就能访问到注册中心了,如下图:
本地服务调用K8S环境中的SpringCloud微服务实战_kubernetes_05
  • 通过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

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

server:
  port: 8080
spring:
  application:
    name: service-consumer
eureka:
  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返回的内容加个前缀返回:
@RestController
public 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);
    }
}
  • 在本地运行此工程,去看注册中心页面,发现已经注册成功:

    本地服务调用K8S环境中的SpringCloud微服务实战_kubernetes_07
  • 在浏览器输入: http://localhost:8080/user/aaa/bbb ,可见服务B的返回内容中有调用服务A时返回的信息,所以调用成功:

    本地服务调用K8S环境中的SpringCloud微服务实战_kubernetes_08
    实战完成,从注册到远程调用都一切正常。

一点小遗憾

  • 在使用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微服务实战_kubernetes_10
  • 此文章的配图是比较细致清晰的,在此转载了:

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

欢迎关注51CTO博客:程序员欣宸

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK