中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當前位置: 首頁 > news >正文

網(wǎng)站開發(fā)工程師的要求站長工具站長之家官網(wǎng)

網(wǎng)站開發(fā)工程師的要求,站長工具站長之家官網(wǎng),wordpress 代碼解讀,自建網(wǎng)站怎么做推廣前言 在一些特殊場景中,我們可能需要使用java或者其他任意語言調(diào)用python腳本或sdk等。本文的需求衍生也不例外于此,python端有sdk,但只能在python中調(diào)用,于是就有了本文章。 常見的調(diào)用方式如jython、python提供http rest接口、…

前言

在一些特殊場景中,我們可能需要使用java或者其他任意語言調(diào)用python腳本或sdk等。本文的需求衍生也不例外于此,python端有sdk,但只能在python中調(diào)用,于是就有了本文章。
常見的調(diào)用方式如jython、python提供http rest接口、python提供rpc實現(xiàn)、java通過jni調(diào)用轉(zhuǎn)換成c的python。每種調(diào)用方式都有優(yōu)缺點,我們更期待一種簡單、快速、功能更自由、低侵入、方便維護的方式來實現(xiàn)。
快速調(diào)研了一下現(xiàn)有的各種實現(xiàn)方式,最后決定采用grpc調(diào)用,好處就是代碼不多,協(xié)議定義簡單方便,兩端協(xié)調(diào)好就可以了,非常適合對sdk、算法、腳本、服務(wù)的調(diào)用,缺點就是更改協(xié)議后,兩邊要重新生成代碼來保持同步,不過在有現(xiàn)成插件的情況下,這能很方便的控制,話不多說,下面貼出詳細做法。

一、定義proto文件

創(chuàng)建一個文件名為script.proto,稍后需要在java端和python端引入

//@ 1 使用proto3語法
syntax = "proto3";
//@ 2 生成多個類(一個類便于管理)
option java_multiple_files = false;
//@ 3 定義調(diào)用時的java包名
option java_package= "com.kamjin.javacallpython.grpc.demo.proto";
//@ 4 生成外部類名
option java_outer_classname = "ScriptProto";
//@ 6. proto包名稱(邏輯包名稱)
package script;import "google/protobuf/struct.proto";//@ 7 定義一個服務(wù)來描述要生成的API接口,類似于Java的業(yè)務(wù)邏輯接口類
service ScriptService{//定義執(zhí)行方法,方法名稱和參數(shù)和返回值都是大駝峰//Note: 這里是 returns,不是 returnrpc Execute (ScriptRequest) returns (ScriptResponse) {}
}//@ 8 定義請求數(shù)據(jù)結(jié)構(gòu)
//字符串數(shù)據(jù)類型
//等號后面的數(shù)字即索引值(表示參數(shù)順序,以防止參數(shù)傳遞順序混亂),服務(wù)啟動后無法更改
//不能使用19000-1999保留數(shù)字
message ScriptRequest{string content = 1;google.protobuf.ListValue extract_params = 2;
}
//@ 9 定義響應(yīng)數(shù)據(jù)結(jié)構(gòu)
message ScriptResponse{string result = 1;
}

二、java/kotlin端

個人習(xí)慣使用kotlin+gradle,此處使用該組合演示,java+maven也可以,主要是gradle配置部分區(qū)別較大,有需求可以評論區(qū)留言

0.創(chuàng)建服務(wù)

創(chuàng)建一個springboot項目,版本為2.x,為了方便起見,需要是web服務(wù),端口默認就可以

1.安裝protobuf插件

在IDEA插件市場搜索protobuf下載安裝,注意作者是HIGAN,不要裝錯了,如圖
在這里插入圖片描述

2.依賴和其他配置

配置模塊的build.gradle.kts文件,
新增依賴和plugin如下:

plugins {//protobuf pluginid("com.google.protobuf") version "0.9.4"...
}dependencies {//grpc clientimplementation("net.devh:grpc-client-spring-boot-starter:2.15.0.RELEASE")implementation("io.grpc:grpc-stub:1.15.1")implementation("io.grpc:grpc-protobuf:1.15.1")...
}

protobuf配置和task配置如下:

import com.google.protobuf.gradle.*
import org.gradle.kotlin.dsl.proto//https://github.com/google/protobuf-gradle-plugin
sourceSets {main {proto {srcDir("src/main/proto")include("**/*.proto")}}test {proto {srcDir("src/test/proto")}}
}
protobuf {protoc {// The artifact spec for the Protobuf Compilerartifact = "com.google.protobuf:protoc:3.17.3"}plugins {// Optional: an artifact spec for a protoc plugin, with "grpc" as// the identifier, which can be referred to in the "plugins"// container of the "generateProtoTasks" closure.id("grpc") {artifact = "io.grpc:protoc-gen-grpc-java:1.40.0"}}generateProtoTasks {ofSourceSet("main").forEach {it.plugins {// Apply the "grpc" plugin whose spec is defined above, without// options. Note the braces cannot be omitted, otherwise the// plugin will not be added. This is because of the implicit way// NamedDomainObjectContainer binds the methods.id("grpc")}}}
}//配置提示proto文件重復(fù)的處理策略
tasks.withType<ProcessResources> {duplicatesStrategy = DuplicatesStrategy.INCLUDE
}

配置完成后點一下gradle的刷新按鈕reload all gradle projects,此時會下載相關(guān)依賴

3.生成代碼

在模塊的src/main目錄下新建名為proto文件夾,將定義好的script.proto文件放入該目錄,運行g(shù)radle task,如圖所示:
在這里插入圖片描述
運行該task后將會生成可以調(diào)用的proto服務(wù)代碼,將在文件夾build/generated/source/proto/main可以找到生成的代碼,一般無需改動該代碼,我們需要使用時直接調(diào)用引入即可。

4.服務(wù)配置

在模塊配置文件application.yaml中配置如下:

grpc:client:scriptServiceGrpc:address: 'static://127.0.0.1:50051'negotiationType: plaintext
  • scriptServiceGrpc是我們在代碼里需要聲明的grpc server名稱,可以任意自定義和在grpc.client下定義多個這樣的條目
  • address指定grpc server端的地址+端口,在當前文章中對應(yīng)的就是python項目中的grpc服務(wù)URL地址

關(guān)于配置項的更多詳情可以查看這里。

5.編寫grpc client代碼

首先編寫一個controller用于調(diào)試代碼

package com.kamjin.javacallpython.grpc.demo.controller.testimport com.kamjin.javacallpython.grpc.demo.handle.*
import com.kamjin.common.ext.*
import org.springframework.beans.factory.annotation.*
import org.springframework.web.bind.annotation.*/*** <p>** </p>** @author kam* @since 2024/01/08*/
@RequestMapping("/test/proto/")
@RestController
class ProtoTestController {@Autowiredlateinit var grpcScriptExecuter: GrpcScriptExecuter@PostMapping("script")fun script(@RequestBody request: MutableMap<String, Any?>): String? {val contentBase64 = request["content_base64"] as String? ?: return ""return this.grpcScriptExecuter.exec(ScriptContent(content = contentBase64.base64Decode(),extractParams = request["extract_params"] as List<String>? ?: mutableListOf())).result}
}

執(zhí)行腳本的GrpcScriptExecuter,內(nèi)容如下:

package com.kamjin.javacallpython.grpc.demo.handleimport com.google.protobuf.*
import com.kamjin.javacallpython.grpc.demo.proto.*
import net.devh.boot.grpc.client.inject.*
import org.springframework.stereotype.*/*** <p>** </p>** @author kam* @since 2024/01/08*/
interface ScriptExecute {fun exec(content: ScriptContent): ScriptExecResult
}data class ScriptContent(val content: String,val extractParams: List<String> = mutableListOf()
)data class ScriptExecResult(val result: String? = null)@Component
class GrpcScriptExecuter : ScriptExecute {@GrpcClient("scriptServiceGrpc")private lateinit var scriptStub: ScriptServiceGrpc.ScriptServiceBlockingStuboverride fun exec(content: ScriptContent): ScriptExecResult {val c = content.contentif (c.isBlank()) return ScriptExecResult()val extractParams = content.extractParamsval r = ScriptProto.ScriptRequest.newBuilder().setContent(c).apply {if (extractParams.isNotEmpty()) {this.extractParams = ListValue.newBuilder().apply {for (ep in extractParams) {this.addValues(Value.newBuilder().setStringValue(ep).build())}}.build()}}.build()try {return ScriptExecResult(scriptStub.execute(r).result)} catch (e: io.grpc.StatusRuntimeException) {throw RuntimeException("script exec error,msg: ${e.message}", e)}}}
  • @GrpcClient("scriptServiceGrpc")的值對應(yīng)的則是上一步中在appliation.yaml中配置的值
  • 當前文件做了兩件事:
    1.定義一個ScriptExecute的interface和請求/響應(yīng)的data class
    2.實現(xiàn)了GrpcScriptExecuter,用于通過調(diào)用grpc server端執(zhí)行腳本內(nèi)容

這樣就完成了java端grpc client的創(chuàng)建。

三、python端

0.安裝protobuf插件

同樣需要安裝protobuf插件,上文已經(jīng)描述過了(idea plugin)不再贅述

1.創(chuàng)建項目

創(chuàng)建一個python venv項目,在模塊中創(chuàng)建一個新的文件夾:proto_test

2.復(fù)制proto文件

把之前定義的script.proto文件復(fù)制到其中,要求和java服務(wù)端放入的文件保持一致,不用做任何改動。

3.生成代碼

轉(zhuǎn)到控制臺,使用pip安裝需要的依賴

pip install grpcio
pip install grpcio-tools googleapis-common-protos

然后進入proto_test目錄,生成相應(yīng)的grpc代碼

python -m grpc_tools.protoc -I . --python_out=. --grpc_python_out=. script.proto

此時會在proto_test目錄下生成文件:script_pb2_grpc.pyscript_pb2.py,后面會用到。

4.編寫grpc server代碼

創(chuàng)建文件:script_server.py,內(nèi)容如下:

import jsonimport grpc
import script_pb2
import script_pb2_grpc
from concurrent import futures
import time_ONE_DAY_IN_SECONDS = 60 * 60 * 24# service impl
class ScriptServicer(script_pb2_grpc.ScriptServiceServicer):def Execute(self, request, context):s = request.contentresult = {}print("content: %s" % s)exec(s, result)# 根據(jù)傳入的參數(shù)提取值data = {}for p in request.extract_params:data[p] = result.get(p, None)return script_pb2.ScriptResponse(result=json.dumps(data))def serve():server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))script_pb2_grpc.add_ScriptServiceServicer_to_server(ScriptServicer(), server)server.add_insecure_port('[::]:50051')server.start()try:while True:time.sleep(_ONE_DAY_IN_SECONDS)except KeyboardInterrupt:server.stop(0)if __name__ == '__main__':serve()

這樣就完成了python端grpc server的創(chuàng)建。

四、驗證

1.啟動java服務(wù):通過IDEA運行WEB服務(wù)
2.啟動python服務(wù):python script_server.py
3.使用postman或者IDEA httpclient調(diào)用接口,這里使用IDEA的http client
定義文件javacallpython-grpc.http

POST http://localhost:8080/test/proto/script
Content-Type: application/json{"content_base64": "aW1wb3J0IG1hdGgKZGVmIGZ1biAobik6CiAgICBkYXRhID0gbgogICAgZGF0YSA9IGRhdGEgKiBtYXRoLnBpCiAgICByZXR1cm4gZGF0YQpyID0gZnVuKDEwKQ==","extract_params": ["r"]
}

運行該調(diào)用,這將會調(diào)用剛剛啟動的web服務(wù)(端口為8080默認)接口:/test/proto/script

  • 此處傳的content_base64是因為json中不支持’‘’‘’'標注的字符串,也就沒法滿足python的縮進要求,故將腳本內(nèi)容轉(zhuǎn)為base64傳入,實際腳本內(nèi)容為:
import math
def fun (n):data = ndata = data * math.pireturn data
r = fun(10)

轉(zhuǎn)為base64后:

aW1wb3J0IG1hdGgKZGVmIGZ1biAobik6CiAgICBkYXRhID0gbgogICAgZGF0YSA9IGRhdGEgKiBtYXRoLnBpCiAgICByZXR1cm4gZGF0YQpyID0gZnVuKDEwKQ==
  • extract_params是表明我們需要提取腳本中變量名稱為r的內(nèi)容的值作為腳本執(zhí)行結(jié)果返回。

python端控制臺打印:
在這里插入圖片描述

http client執(zhí)行結(jié)果:

在這里插入圖片描述

這表明帶import的腳本執(zhí)行成功,并正確返回了我們想要提取的值

參考文章

1.擁抱云原生,Java與Python基于gRPC通信
2.base64和字符串互轉(zhuǎn)
3.Import Lib not working with exec function?
4.yidongnan/grpc-spring-boot-starter
5.google/protobuf-gradle-plugin

結(jié)語

本文實現(xiàn)了通過grpc在java端傳入腳本內(nèi)容,在python端執(zhí)行的腳本的實現(xiàn)方法,性能狀況未測試,后續(xù)如果有時間會對其進行使用驗證,如果發(fā)現(xiàn)問題,可以做相關(guān)改進,會在本文進行更新,本文的實現(xiàn)對實際項目中的使用具有一定的參考價值。
后面會繼續(xù)更新分享更多相關(guān)內(nèi)容,請多多關(guān)注~

最后,各位看眾可以思考一下:

為什么以上做法可以成功執(zhí)行帶import的腳本?

http://www.risenshineclean.com/news/39640.html

相關(guān)文章:

  • 成都網(wǎng)站開發(fā)排名廈門關(guān)鍵詞排名優(yōu)化
  • 北京網(wǎng)站設(shè)計首選 新鴻儒360免費建站教程
  • wordpress標簽生成圖片基礎(chǔ)建站如何提升和優(yōu)化
  • wordpress 連接后臺關(guān)鍵詞優(yōu)化公司費用多少
  • 網(wǎng)站內(nèi)移動的圖片怎么做的深圳網(wǎng)絡(luò)優(yōu)化公司
  • 公司備案網(wǎng)站負責人是誰網(wǎng)站推廣軟件哪個好
  • 淄博張店做網(wǎng)站的公司百度網(wǎng)站客服電話
  • 網(wǎng)站建設(shè)新聞發(fā)布注意事項互聯(lián)網(wǎng)怎么賺錢
  • 建設(shè)網(wǎng)站的英語怎么說做網(wǎng)站的網(wǎng)絡(luò)公司
  • 微信小程序頁面模板seo文章是什么
  • 廣水市建設(shè)局網(wǎng)站線上培訓(xùn)
  • 建設(shè)網(wǎng)站的方案什么叫做優(yōu)化
  • rust做網(wǎng)站微商引流被加方法精準客源
  • 如何建設(shè)成為營銷網(wǎng)站百度客服電話24小時人工服務(wù)熱線
  • 向日葵域名怎么做網(wǎng)站成都網(wǎng)站搭建優(yōu)化推廣
  • 手機動態(tài)網(wǎng)站開發(fā)教程網(wǎng)絡(luò)營銷的四大特點
  • 如何做網(wǎng)站本地服務(wù)器嗎廣告投放策略
  • 江蘇省建設(shè)人才網(wǎng)站軟文文案案例
  • 蘭州新站seo如何找推廣平臺
  • 假網(wǎng)站怎么做呢百度信息流投放技巧
  • 怎么提高網(wǎng)站曝光武漢seo優(yōu)化服務(wù)
  • 高能建站系統(tǒng)怎么收費查詢網(wǎng)站流量的網(wǎng)址
  • 網(wǎng)站備案沒公司網(wǎng)絡(luò)口碑營銷的成功案例
  • 主流跨境電商平臺有哪些?山東服務(wù)好的seo
  • 做酒店網(wǎng)站的公司百度一下子就知道了
  • 個人網(wǎng)站怎么做視頻人工智能培訓(xùn)心得
  • 北京網(wǎng)頁制作網(wǎng)站搜索引擎網(wǎng)站優(yōu)化推廣
  • 專用主機網(wǎng)站建設(shè)企業(yè)郵箱域名
  • 鹽城網(wǎng)站建設(shè)流程百度在線使用網(wǎng)頁版
  • WordPress 升級 php蘇州百度快速排名優(yōu)化