• (1)SpringCloud 整合Python


    文章目录

    1.引言

    说到Python这门语言,应该都会很熟悉,近几年来Python大火,几乎都到了人人喊着:“人生苦短,我学Python”的境地,确实Python在机器学习方面有着得天独厚的优势,在Python语言中拥有很多现成的机器学习函数库,然后在Web开发中还是有着很多人使用Java作为服务器的后台语言,尤其是近几年来微服务的兴起,也有着越来越多的人使用SpringCloud(基于Java语言实现的微服务框架),因此就产生了这么一个需求:能否将Python的机器学习算法集成到SpringCloud中,作为我们Web系统的服务,当我们自己使用Python实现了一个新的机器学习算法的时候,可以同时为他人提供服务。用户在Web端提供数据,而Web平台提供算法进行计算,同时反馈给用户)。 要想实现上面的需求,其实就是存在着整合SpringCloud 整合Python的必要性。因此我查了SpringCloud的官网,还真的提供了整合Python语言的解决方案(其实是整合第三方语言的解决方案)。这个解决方案叫做:sidecar。通过使用**sidecar**我们可以将Python接口注册为SpringCloud的一个服务,实现Java(因为SpringCloudJava语言的一款框架)和Python的双向通信,即:Python可以调用Java语言的接口,同时Java也可以调用Python语言的接口。

    2. 什么是sidecar

    我们刚刚说了使用sidecar可以将SpringCloud和第三方语言整合,那什么是sidecar呢?说白了sidecar就是springcloud提供的一个工具,使用该工具将第三方的rest接口集成到springcloud中来。那么如何使用sidecar呢?首先我们看一下官网的描述。

    2.1 Polyglot支持Sidecar(官网描述)

    Spring Cloud Netflix Sidecar 包含一个简单的http api来获取给定服务的所有实例(即主机和端口)。然后可以通过从Eureka获取其路由条目的嵌入式Zuul代理来代理服务调用。可以通过主机查找或通过Zuul代理访问Spring Cloud Config服务器。但是第三方程序必须执行健康检查,以便Sidecar可以向应用程序启动或关闭时向eureka报告**(意思就是说:第三方程序必须提供一个接口告诉Spring Cloud自身是否还在运行?)**。如何使用Sidecar呢?官网给出了如下的步骤:

    2.1.1 使用Sidecar步骤

    • 添加Java包依赖

    如果要在项目中包含Sidecar,需要使用org.springframework.cloudartifact id spring-cloud-netflix-sidecar的依赖。

    • 注解启动Sidecar

    使用@EnableSidecar创建Spring Boot应用程序。此注释包括@EnableCircuitBreaker@EnableDiscoveryClient@EnableZuulProxy

    • 修改配置

    配置Sidecar,应该将sidecar.portsidecar.health-uri添加到application.ymlsidecar.port属性是非jvm应用程序正在侦听的端口。这样,Sidecar可以使用Eureka正确注册该应用。sidecar.health-uri是可以在非jvm应用程序上访问的,可以模拟Spring Boot健康指标。它应该返回一个json文档,如下所示:

    {
      "status":"UP"
    }
    
    • 1
    • 2
    • 3

    以下是Sidecar应用程序的application.yml示例:

    server:
      port: 5678
    spring:
      application:
        name: sidecar
    
    sidecar:
      port: 8000
      health-uri: http://localhost:8000/health.json
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    2.1.2 Java调用非JVM程序接口

    我们使用Sidecar将第三方程序接口(比如Python)注册到SpringCloud之中,如何使用Python接口呢?这时候就非常简单了,此时我们就可以将Python接口当作Java接口进行调用(其实时通过springcloud去调用Sidecar,然后通过Sidecar去转发我们的程序请求)。

    2.1.3 非JVM接口调用Java接口

    因为非JVM应用 被注册到SpringCloud之中,对于第三方应用程序来说,整个SpringCloud的内容,我们都可以进行调用了,比如我们有一个Java服务叫做customers,那么我们就可以通过url来调用,比如http://localhost:5678/customers(假设Sidecar在端口5678上),因为配置服务器(configserver)也属于SpringCloud的一个服务,因此非JVM语言也可以调用配置服务器的配置,比如使用如下的urlhttp:// localhost:5678/configserver

    2.2 Sidecar总结

    看了官网的描述,似乎我们还是抓不住重点,到底应该如何结合Sidecar和第三方程序呢?依旧是如此的茫然。下面我着重说一下官网提供的重点:

    • Sidecar是一个用于监听非JVM应用程序(可以是Python或者Node或者Php等等)的一个工具,通过Sidecar可以实现Java和第三方应用程序的双向交互
    • 第三方应用程序必须要实现一个接口,实时向Sidecar报告自己的状态,告诉Sidecar自己还在运行着。
    • Sidecar应用程序必须和第三方应用程序运行在同一台电脑上,也就是说他们之间是localhost,不能是ip访问(官网未提及)

    3.PythonSpringCloud整合实例

    前面说了这么多理论性的东西,似乎我们只知道了一个事情:通过Sidecar可以实现SpringCloud和第三方应用程序的整合,就比如我们的Python,可以利用SidecarPython集成到我们的微服务中来,然后我们就可以利用Python强大的机器学习算法了。

    说了这么多,往往不如一个实例来的更加直接,现在我就使用Python来和SpringCloud整合。在我的程序结构如下所示:

    • python接口中会提供一个服务功能:获取Python用户名和密码,用户名为:python,密码为python。同时python应该还提供一个健康接口,报告自己的健康状态
    • Java服务会提供两个接口(JavaUser,PythonUser)JavaUser方法用于获得Java用户名和密码,用户名为:java,密码为javaPythonUser方法会调用python服务,获得Python用户名和密码。

    3.1 定义Python服务

    Python中,我使用flask提供Web服务,代码如下:

    import json
    from flask import Flask, Response
    app = Flask(__name__)
    @app.route("/health")
    def health():
        result = {'status': 'UP'}
        return Response(json.dumps(result), mimetype='application/json')
    @app.route("/getUser")
    def getUser():
        result = {'username': 'python', 'password': 'python'}
        return Response(json.dumps(result), mimetype='application/json')
    app.run(port=3000, host='0.0.0.0')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    代码解释:

    • Python服务监听3000接口
    • health方法用于给Sidecar提供健康接口,用于实时向Sidecar提供自己的健康状态。
    • getUserPython向外界提供的服务,提供Python用户的用户名和密码

    3.2 定义SpringCloud注册中心

    application.properties配置文件

    server.port=8000
    spring.application.name=eureka-server
    eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/
    eureka.client.registerWithEureka=false
    eureka.client.fetchRegistry=false
    
    • 1
    • 2
    • 3
    • 4
    • 5

    main方法

    package com.example.demo;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
    
    @EnableEurekaServer
    @SpringBootApplication
    public class DemoApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(DemoApplication.class, args);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    代码解释:

    • 注册中心启动端口:8000

    3.3 定义sidecar

    main方法

    package com.example.demo;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.sidecar.EnableSidecar;
    @EnableSidecar
    @SpringBootApplication
    public class PySidecarApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(PySidecarApplication.class, args);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    application.properties配置文件

    spring.application.name=py-sidecar
    server.port=8001
    sidecar.port=3000
    sidecar.health-uri=http://localhost:${sidecar.port}/health
    hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
    ribbon.ConnectTimeout=5000
    ribbon.ReadTimeout=5000
    eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    代码解释:

    • main方法使用了@EnableSidecar注解
    • sidecar.port代表第三方程序运行的端口(比如上方的Python),所以监听端口为3000
    • server.port代表sidecar运行的端口
    • spring.application.name代表sidecar的应用名字**(后面要用到)**
    • sidecar.health-uriPython健康接口,应指向python的健康服务

    3.4 定义Java服务

    Java服务

    package com.example.demo;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    @RestController
    public class JavaController {
        @Autowired
        private RestTemplate restTemplate;
        @RequestMapping("/java-user")
        public String JavaUser() {
            return "{'username': 'java', 'password': 'java'}"  ;
        }
        @RequestMapping("/python-user")
        public String PythonUser() {
            return restTemplate.getForEntity("http://py-sidecar/getUser", String.class).getBody();
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    main方法

    package com.example.demo;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.SpringCloudApplication;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    @SpringCloudApplication
    public class RibbonConsumerApplication {
    	@Bean
    	@LoadBalanced
    	RestTemplate restTemplate() {
    		return new RestTemplate();
    	}
    	public static void main(String[] args) {
    		SpringApplication.run(RibbonConsumerApplication.class, args);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    application.properties

    spring.application.name=java-service
    server.port=8002
    eureka.client.service-url.defaultZone=http://localhost:8000/eureka/
    
    • 1
    • 2
    • 3

    代码解释:

    • server.port代表Java服务运行的端口
    • spring.application.name代表Java服务应用的名字**(后面要用到)**
    • PythonUser方法中,Java调用了Python服务,将Python用户返回**(注意:在这里Java语言调用了Python的接口,实现了JavaPython的通信)**
    • JavaUser方法中,直接返回了Java用户的信息

    3.5 服务相互调用

    在服务调用之前,我们先回顾一下代码都做了什么样子的事情:

    • 定义了一个Python服务,运行在端口3000
    • 定义了一个sidecar,运行在短就8001,监听Python端口3000,应用名字为py-sidecar
    • 定义了一个Java服务,运行在端口8002,应用名字为java-service
    • 服务的启动顺序:Python服务,注册中心,py-sidecarjava-service

    3.5.1 调用Java原生服务

    对于Java原生服务的调用没有什么特别,直接访问URL即可,如:http://localhost:8002/java-user

    在这里插入图片描述

    3.5.2 Java调用Python服务

    java-service服务的PythonUser中,Java调用了Python的服务,使用restTemplate模板,通过:http://{service_id}/{method}实现了对Python服务的调用**(这里我们调用的时Java的端口,返回的是Python的数据内容)**

    在这里插入图片描述

    3.5.3 通过sidecar调用Java服务

    我们使用了sidecar,所以我们可以使用sidecar实现对Java服务的调用,比如:http://{host}:{port}/{service_id}/{method},其中:

    • hostsidecar的主机地址
    • portsidecar的端口地址
    • service_idJava服务的id
    • methodJava服务的具体方法地址

    如果我们想通过sidecar获得Java用户的对象,可以这么写:http://localhost:8001/java-service/java-user

    在这里插入图片描述

    3.6 实例代码的下载地址

  • 相关阅读:
    MySQL高级语句(二)
    11.15 知识总结(模板层、模型层)
    【数据结构-树】树及森林的定义
    [旭日X3派] 初识篇 - 01
    我在玛莎拉蒂的广告上,加了9个特效后,科技感拉满!
    使用Typora编辑markdown上传CSDN时图片大小调整麻烦问题
    Tomcat的日志接收文件catalina.out nohup.out说明
    基于51单片机的八路多路温度测控系统proteus仿真原理图PCB
    微信小程序自定义组件及会议管理与个人中心界面搭建
    【网页制作课作业】用HTML+CSS制作一个简单的学校网页(9页)
  • 原文地址:https://blog.csdn.net/m0_67402914/article/details/126620535