{"id":189,"date":"2023-01-23T11:47:43","date_gmt":"2023-01-23T02:47:43","guid":{"rendered":"https:\/\/hirabay.net\/?p=189"},"modified":"2023-01-23T15:34:22","modified_gmt":"2023-01-23T06:34:22","slug":"%e3%80%90%e5%88%9d%e5%bf%83%e8%80%85%e5%90%91%e3%81%91%e3%80%91springboot%e3%81%a7grpc%e3%82%92%e5%ae%9f%e8%a3%85%e3%81%97%e3%81%a6%e3%81%bf%e3%81%9f","status":"publish","type":"post","link":"https:\/\/hirabay.net\/?p=189","title":{"rendered":"\u3010\u521d\u5fc3\u8005\u5411\u3051\u3011SpringBoot\u3067gRPC\u3092\u5b9f\u88c5\u3057\u3066\u307f\u305f"},"content":{"rendered":"\n<p>gRPC\u3092SpringBoot\u3067\u5b9f\u88c5\u3059\u308b\u6a5f\u4f1a\u304c\u3042\u308a\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<p>\u3044\u308d\u3044\u308d\u306a\u30b5\u30a4\u30c8\u304c\u3042\u308b\u306e\u3067\u3059\u304c\u3001\u696d\u52d9\u3067\u3084\u308d\u3046\u3068\u3059\u308b\u3053\u3068\u3092\u3059\u3079\u3066\u7406\u89e3\u3059\u308b\u306b\u306f\u3042\u3061\u3053\u3061\u3092\u63a2\u3057\u56de\u308b\u5fc5\u8981\u304c\u3042\u3063\u3066\u5927\u5909\u3067\u3057\u305f\u3002\u3002\u3002<\/p>\n\n\n\n<p>\u305d\u3093\u306a\u7d4c\u9a13\u304b\u3089\u3001\u3053\u306e\u8a18\u4e8b\u3067\u306f<br><span class=\"keiko_yellow\"><strong>\u5b9f\u52d9\u3067\u6c17\u306b\u3059\u308b\u3067\u3042\u308d\u3046\u3053\u3068\u3092\u300c\u7db2\u7f85\u7684\u306b\u300d\u300c\u30b3\u30d4\u30da\u3067\u4f7f\u3048\u308b\u3088\u3046\u306b\u300d<\/strong><\/span>\u307e\u3068\u3081\u3066\u307f\u307e\u3057\u305f\uff01<\/p>\n\n\n\n<div class=\"toc\"><br \/>\n<b>Warning<\/b>:  Undefined array key \"is_admin\" in <b>\/home\/c4179872\/public_html\/hirabay.net\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>110<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_category_top\" in <b>\/home\/c4179872\/public_html\/hirabay.net\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>115<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_top\" in <b>\/home\/c4179872\/public_html\/hirabay.net\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>122<\/b><br \/>\n    <div id=\"toc_container\" class=\"sgb-toc--bullets js-smooth-scroll\">\n      <p class=\"toc_title\">\u76ee\u6b21 <\/p>\n      <ul class=\"toc_list\">\n  <li class=\"first\">\n    <a href=\"#i-0\">\u524d\u63d0<\/a>\n  <\/li>\n  <li>\n    <a href=\"#i-1\">\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb<\/a>\n    <ul class=\"menu_level_1\">\n      <li class=\"first\">\n        <a href=\"#i-2\">\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u6210<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-3\">.proto\u30d5\u30a1\u30a4\u30eb\u4f5c\u6210<\/a>\n      <\/li>\n      <li class=\"last\">\n        <a href=\"#i-4\">repository\u3078upload<\/a>\n      <\/li>\n    <\/ul>\n  <\/li>\n  <li>\n    <a href=\"#i-5\">gRPC\u30b5\u30fc\u30d0\u30fc<\/a>\n    <ul class=\"menu_level_1\">\n      <li class=\"first\">\n        <a href=\"#i-6\">\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u6210<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-7\">gRPC\u30b5\u30fc\u30d0\u306e\u5b9f\u88c5<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-8\">\u5358\u4f53\u30c6\u30b9\u30c8<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-9\">\u7d50\u5408\u8a66\u9a13<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-10\">\u52d5\u4f5c\u78ba\u8a8d<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-11\">\u30e1\u30c8\u30ea\u30af\u30b9<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-12\">TLS<\/a>\n      <\/li>\n      <li class=\"last\">\n        <a href=\"#i-13\">\u8ca0\u8377\u8a66\u9a13<\/a>\n      <\/li>\n    <\/ul>\n  <\/li>\n  <li class=\"last\">\n    <a href=\"#i-14\">gRPC\u30af\u30e9\u30a4\u30a2\u30f3\u30c8<\/a>\n    <ul class=\"menu_level_1\">\n      <li class=\"first\">\n        <a href=\"#i-15\">\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u6210<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-16\">gRPC\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u5b9f\u88c5<\/a>\n      <\/li>\n      <li>\n        <a href=\"#i-17\">\u5358\u4f53\u30c6\u30b9\u30c8<\/a>\n      <\/li>\n      <li class=\"last\">\n        <a href=\"#i-18\">TLS<\/a>\n      <\/li>\n    <\/ul>\n  <\/li>\n<\/ul>\n\n      \n    <\/div><\/div><h2 class=\"wp-block-heading\" id=\"i-0\">\u524d\u63d0<\/h2>\n\n\n<p><\/p><div class=\"arconix-list\" data-arconix-icon=\"fa-chevron-circle-right\" data-arconix-color=\"black\">\n<ul>\n<li>\u30d3\u30eb\u30c9\u30c4\u30fc\u30eb\uff1aGradle<\/li>\n<li>\u7aef\u672b\uff1aMac<\/li>\n<li>SpringBoot\uff1a2.6.4<\/li>\n<li>\u6b63\u78ba\u3055\u3088\u308a\u3082\u5206\u304b\u308a\u3084\u3059\u3055\u91cd\u8996<\/li>\n<\/ul>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-1\">\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb<\/h2>\n\n\n\n<p>gRPC\u3067\u306f<code>.proto<\/code>\u62e1\u5f35\u5b50\u306e\u30d5\u30a1\u30a4\u30eb\u3067\u30b9\u30ad\u30fc\u30de\u3092\u5b9a\u7fa9\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<p>Rest API\u3067\u3044\u3046IF\u4ed5\u69d8\u66f8\u306e\u3088\u3046\u306a\u3082\u306e\u3067\u3059\u3002<br>Rest API\u3067\u306f\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3068\u3057\u3066\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3068\u306f\u5225\u3067\u7ba1\u7406\u3092\u3057\u307e\u3059\u304c\u3001<br>gRPC\u3067\u306f\u3053\u306e\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u81ea\u4f53\u304c\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b3\u30fc\u30c9\u306e\u4e00\u90e8\u306b\u5909\u63db\u3055\u308c\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u306e\u7ba1\u7406\u306f\u3001\u3053\u3053\u3067\u306fserver\u3068\u3082client\u3068\u3082\u5207\u308a\u96e2\u3057\u305fjar\u3067\u7ba1\u7406\u3059\u308b\u3053\u3068\u3068\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u6210<\/h3>\n\n\n\n<p><a href=\"https:\/\/start.spring.io\/\" rel=\"noreferrer noopener\" target=\"_blank\">https:\/\/start.spring.io\/<\/a>&nbsp;\u3067\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002<br>\u4f9d\u5b58\u306f\u7279\u306b\u8ffd\u52a0\u3057\u306a\u304f\u3066OK<\/p>\n\n\n\n<p>\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff06\u89e3\u51cd\u5f8c\u3001<code>build.gradle<\/code>\u3092\u4fee\u6b63\u3057\u307e\u3059<br>\uff08\u4fee\u6b63\u90e8\u5206\u306e\u307f\u629c\u7c8b\uff09<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-groovy\" data-file=\"build.gradle\" data-lang=\"Groovy\"><code>\/\/ \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8ffd\u52a0\nplugins {\n    id 'maven-publish'\n    id \"io.github.lognet.grpc-spring-boot\" version '4.6.0'\n}\n\n\/\/ jar\u30d5\u30a1\u30a4\u30eb\u95a2\u9023\u306e\u8a2d\u5b9a\njar {\n    enabled = true\n    archiveClassifier = ''\n}\nbootJar {\n    enabled = false\n}\n\n\/\/ publish\u306e\u8a2d\u5b9a\npublishing {\n    publications {\n        mavenPlugin(MavenPublication) {\n            from components.java\n        }\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p><code>io.github.lognet.grpc-spring-boot<\/code>plugin\u3092\u8ffd\u52a0\u3059\u308b\u3060\u3051\u3067\u3001<br>grpc\u306e\u5b9f\u88c5\u306b\u5fc5\u8981\u306a\u4f9d\u5b58\u304c\u3059\u3079\u3066\u81ea\u52d5\u3067\u8ffd\u52a0\u3055\u308c\u307e\u3059\u2728<\/p>\n\n\n\n<p>\u53c2\u8003\uff1a<\/p>\n\n\n<p><\/p><div class=\"linkcard\"><div class=\"lkc-external-wrap\"><a class=\"lkc-link no_icon\" href=\"https:\/\/github.com\/LogNet\/grpc-spring-boot-starter\/blob\/master\/grpc-spring-boot-starter-gradle-plugin\/README.adoc\" target=\"_blank\" rel=\"external noopener\"><div class=\"lkc-card\"><div class=\"lkc-info\"><img loading=\"lazy\" decoding=\"async\" class=\"lkc-favicon\" src=\"https:\/\/www.google.com\/s2\/favicons?domain=github.com\" alt=\"\" width=\"16\" height=\"16\"><div class=\"lkc-domain\">GitHub<\/div><\/div><div class=\"lkc-content\"><figure class=\"lkc-thumbnail\"><img decoding=\"async\" class=\"lkc-thumbnail-img\" src=\"\/\/hirabay.net\/wp-content\/uploads\/pz-linkcard\/cache\/0b260420e3651ee322ee5f49e64752aaae8cdc49d35b4ce0792bbd5c5dc4e099.jpeg\" alt=\"\"><\/figure><div class=\"lkc-title\"><div class=\"lkc-title-text\">grpc-spring-boot-starter\/README.adoc at master \u00b7 LogNet\/grpc-spring-boot-starter<\/div><\/div><div class=\"lkc-url\">https:\/\/github.com\/LogNet\/grpc-spring-boot-starter\/blob\/master\/grpc-spring-boot-starter-gradle-plugin\/README.adoc<\/div><div class=\"lkc-excerpt\">Spring Boot starter module for gRPC  framework. . Contribute to LogNet\/grpc-spring-boot-starter development by creating an account on GitHub.<\/div><\/div><div class=\"clear\"><\/div><\/div><\/a><\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-3\">.proto\u30d5\u30a1\u30a4\u30eb\u4f5c\u6210<\/h3>\n\n\n\n<p><code>src\/main\/proto<\/code>\u914d\u4e0b\u306b\u4ee5\u4e0b\u306e\u3088\u3046\u306a\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u3092\u4f5c\u6210\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-protobuf\" data-file=\"sample.proto\" data-lang=\"Protocol Buffers\"><code>syntax = \"proto3\";\n\noption java_multiple_files = true;\n\/\/ \u81ea\u52d5\u751f\u6210\u3055\u308c\u308bJava\u30af\u30e9\u30b9\u306epackege\u306b\u5bfe\u5fdc\noption java_package = \"rhirabay.grpc.sample\";\n\/\/ \u81ea\u52d5\u751f\u6210\u3055\u308c\u308bJava\u30af\u30e9\u30b9\u540d\u306b\u4f7f\u308f\u308c\u308b\uff08server, client\u5b9f\u88c5\u6642\u306b\u306f\u610f\u8b58\u3057\u306a\u3044\u304b\u3082\uff09\noption java_outer_classname = \"Greeter\";\n\n\/\/ \u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u81ea\u4f53\u306epackage\npackage greet;\n\n\/\/ \u30b5\u30fc\u30d3\u30b9\u306e\u5b9a\u7fa9\nservice Greet{\n  rpc greeting (GreetRequest) returns (GreetResponse);\n}\n\n\/\/ \u30ea\u30af\u30a8\u30b9\u30c8\u5b9a\u7fa9\uff08\u3053\u306e\u540d\u524d\u3067Java\u30af\u30e9\u30b9\u304c\u81ea\u52d5\u751f\u6210\u3055\u308c\u308b\uff09\nmessage GreetRequest{\n  \/\/ Java\u30af\u30e9\u30b9\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u8a72\u5f53\uff08\u53f3\u5074\u306e\u6570\u5b57\u306f\u30bf\u30b0 \u203b\u4e00\u610f\u306b\u3064\u3051\u308c\u3070OK\uff09\n  \/\/ Java\u306e\u578b\u3068\u306e\u5bfe\u5fdc: https:\/\/developers.google.com\/protocol-buffers\/docs\/proto3#scalar\n  string name = 1;\n}\n\n\/\/ \u30ec\u30b9\u30dd\u30f3\u30b9\u5b9a\u7fa9\uff08\u3053\u306e\u540d\u524d\u3067Java\u30af\u30e9\u30b9\u304c\u81ea\u52d5\u751f\u6210\u3055\u308c\u308b\uff09\nmessage GreetResponse{\n  \/\/ Java\u30af\u30e9\u30b9\u306e\u30d5\u30a3\u30fc\u30eb\u30c9\u306b\u8a72\u5f53\n  string message = 1;\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-4\">repository\u3078upload<\/h3>\n\n\n\n<p>\u4eca\u56de\u306flocal\u306emaven repository\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u306a\u306e\u3067<code>publishToMavenLocal<\/code>\u30bf\u30b9\u30af\u3092\u5b9f\u884c\u3059\u308c\u3070OK\uff01<br>\u88cf\u3067\u30af\u30e9\u30b9\u306e\u81ea\u52d5\u751f\u6210\uff08<code>generateProto<\/code>\uff09\u3001jar\u306e\u751f\u6210\uff08<code>jar<\/code>\uff09\u3092\u3057\u3066\u304f\u308c\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u751f\u6210\u3055\u308c\u305fjar\u3092server, client\u3067\u53d6\u308a\u8fbc\u3081\u3070\u3001\u81ea\u52d5\u751f\u6210\u3055\u308c\u305f\u30af\u30e9\u30b9\u3092\u5229\u7528\u3067\u304d\u307e\u3059\uff01<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-5\">gRPC\u30b5\u30fc\u30d0\u30fc<\/h2>\n\n\n\n<p>gRPC\u306e\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u53d7\u3051\u4ed8\u3051\u308b\u30b5\u30fc\u30d0\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u5b9f\u88c5\u3057\u3066\u3044\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-6\">\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u6210<\/h3>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"https:\/\/start.spring.io\/\" target=\"_blank\">https:\/\/start.spring.io\/<\/a>&nbsp;\u3067\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002<br><code>Spring Web<\/code>\u3092\u4f9d\u5b58\u306b\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff06\u89e3\u51cd\u5f8c\u3001<code>build.gradle<\/code>\u3092\u4fee\u6b63\u3057\u307e\u3059<br>\uff08\u4fee\u6b63\u90e8\u5206\u306e\u307f\u629c\u7c8b\uff09<\/p>\n\n\n\n<p>\u203b\u88dc\u8db3<br>grpc\u30b5\u30fc\u30d0\u3060\u3051\u3060\u3068web\u3082\u8981\u3089\u306a\u3044\u306e\u3067\u3059\u304c\u3001\u5f8c\u8ff0\u306e\u30e1\u30c8\u30ea\u30af\u30b9\u53c2\u7167\u3067\u4f7f\u7528\u3059\u308b\u306e\u3067\u5148\u306b\u8ffd\u52a0\u3057\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-file=\"build.gradle\" data-lang=\"Java\"><code>\/\/ \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8ffd\u52a0\nplugins {\n    id \"io.github.lognet.grpc-spring-boot\" version '4.6.0'\n}\n\nrepositories {\n\tmavenCentral()\n\tmavenLocal() \/\/ local repository\u5229\u7528\n}\n\ndependencies {\n    \/\/ \u5148\u307b\u3069upload\u3057\u305fproto\u306e\u53d6\u308a\u8fbc\u307f\n\timplementation 'rhirabay:proto:+'\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-7\">gRPC\u30b5\u30fc\u30d0\u306e\u5b9f\u88c5<\/h3>\n\n\n\n<p><code>&lt;.proto service\u540d&gt;.&lt;.proto service\u540d&gt;ImplBase<\/code>\u3092\u7d99\u627f\u3057\u3066\u5b9f\u88c5\u3057\u307e\u3059\u3002<br>\u4eca\u56de\u3067\u3042\u308c\u3070\u3001service\u540d\u306b<code>Greet<\/code>\u3092\u6307\u5b9a\u3057\u3066\u3044\u308b\u306e\u3067<code>GreetGrpc.GreetImplBase<\/code>\u3092\u7d99\u627f\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>import io.grpc.stub.StreamObserver;\nimport org.lognet.springboot.grpc.GRpcService;\nimport rhirabay.grpc.sample.GreetGrpc;\nimport rhirabay.grpc.sample.GreetRequest;\nimport rhirabay.grpc.sample.GreetResponse;\n\n\/\/ @GRpcService\u3092\u4ed8\u4e0e\u3059\u308b\u3068\u3001grpc\u306eservice\u3068\u3057\u3066\u8a8d\u8b58\u3055\u308c\u308b\n@GRpcService\npublic class SampleService extends GreetGrpc.GreetImplBase {\n    @Override\n    public void greeting(GreetRequest request, StreamObserver&lt;GreetResponse&gt; responseObserver) {\n        GreetResponse response = GreetResponse.newBuilder()\n                .setMessage(\"Hello, \" + request.getName() + \".\")\n                .build();\n        responseObserver.onNext(response);\n        responseObserver.onCompleted();\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p>Override\u3059\u308b\u30e1\u30bd\u30c3\u30c9\u306f\u3001.proto\u306eservice\u5b9a\u7fa9\u3068\u5bfe\u5fdc\u3057\u3066\u3044\u307e\u3059\u3002<br>\u4eca\u56de\u306f\u3001\u30ea\u30af\u30a8\u30b9\u30c8\u3067\u53d7\u3051\u53d6\u3063\u305f\u540d\u524d\u3092\u4f7f\u3063\u3066\u3042\u3044\u3055\u3064\u3059\u308b\u3088\u3046\u306a\u611f\u3058\u306b\u5b9f\u88c5\u3057\u3066\u307f\u307e\u3057\u305f\u3002<\/p>\n\n\n\n<p>\uff08\u30c7\u30d5\u30a9\u30eb\u30c8\u306e\u307e\u307e\u3067\u3059\u304c\uff09port\u3060\u3051\u6307\u5b9a\u3057\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-yaml\" data-file=\"application.yaml\" data-lang=\"Yaml\"><code>grpc:\n  port: 6565<\/code><\/pre><\/div>\n\n\n\n<p>\u3053\u308c\u3060\u3051\uff01<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-8\">\u5358\u4f53\u30c6\u30b9\u30c8<\/h3>\n\n\n\n<p>Service\u30af\u30e9\u30b9\u306e\u5358\u4f53\u30c6\u30b9\u30c8\u3092\u5b9f\u88c5\u3057\u307e\u3059\u3002<br>\u5358\u4f53\u30c6\u30b9\u30c8\u3067\u306f<code>responseObserver.onNext()<\/code>\u3092\u3069\u3093\u306a\u5f15\u6570\u3067\u5b9f\u884c\u3057\u305f\u304b\u304c\u30c6\u30b9\u30c8\u3067\u304d\u308c\u3070\u5341\u5206\u306a\u306f\u305a\ud83e\udd14<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>import io.grpc.stub.StreamObserver;\nimport org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.InjectMocks;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\nimport rhirabay.grpc.sample.GreetRequest;\nimport rhirabay.grpc.sample.GreetResponse;\n\nimport static org.mockito.ArgumentMatchers.any;\nimport static org.mockito.Mockito.doNothing;\nimport static org.mockito.Mockito.verify;\n\n@ExtendWith(MockitoExtension.class)\nclass SampleServiceTest {\n    @InjectMocks\n    private SampleService sampleService;\n\n    @Mock\n    private StreamObserver&lt;GreetResponse&gt; responseObserver;\n\n    @Test\n    void mock_response() {\n        doNothing().when(responseObserver).onNext(any());\n        doNothing().when(responseObserver).onCompleted();\n\n        var request = GreetRequest.newBuilder()\n                .setName(\"Ryo\")\n                .build();\n\n        sampleService.greeting(request, responseObserver);\n\n        var expected = GreetResponse.newBuilder()\n                .setMessage(\"Hello, Ryo.\")\n                .build();\n        verify(responseObserver).onNext(expected);\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u7d50\u5408\u8a66\u9a13<\/h3>\n\n\n\n<p>gRPC\u30b5\u30fc\u30d0\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5168\u4f53\u306e\u8a66\u9a13\u3092\u5b9f\u88c5\u3057\u3066\u307f\u307e\u3059\u3002<br>\u5f8c\u7d9a\u306eClient\u306e\u5b9f\u88c5\u306b\u3082\u51fa\u3066\u304d\u307e\u3059\u304c\u3001BlockingStub\u3092\u4f7f\u7528\u3057\u3066\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u9001\u308a\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>import io.grpc.ManagedChannel;\nimport io.grpc.ManagedChannelBuilder;\nimport org.junit.jupiter.api.Test;\nimport org.lognet.springboot.grpc.context.LocalRunningGrpcPort;\nimport org.springframework.boot.test.context.SpringBootTest;\nimport org.springframework.test.context.ActiveProfiles;\nimport rhirabay.grpc.sample.GreetGrpc;\nimport rhirabay.grpc.sample.GreetRequest;\n\n@SpringBootTest(\n\t\tclasses = GrpcApplication.class,\n\t\tproperties = \"grpc.port=0\" \/\/ \u30e9\u30f3\u30c0\u30e0\u30dd\u30fc\u30c8\n)\n@ActiveProfiles(\"test\")\nclass GrpcApplicationTests {\n\t@LocalRunningGrpcPort \/\/ \u8d77\u52d5\u3057\u305f\u30b5\u30fc\u30d0\u306eport\u3092inject\u3057\u3066\u304f\u308c\u308b\n\tprivate int runningPort;\n\n\t@Test\n\tvoid test() {\n\t\tManagedChannel channel = ManagedChannelBuilder.forAddress(\"localhost\", runningPort)\n\t\t\t\t.usePlaintext()\n\t\t\t\t.build();\n\n\t\tvar stub = GreetGrpc.newBlockingStub(channel);\n\n\t\tvar request = GreetRequest.newBuilder()\n\t\t\t\t.setName(\"Ryo\")\n\t\t\t\t.build();\n\t\tvar actual = stub.greeting(request).getMessage();\n\t\tvar expected = \"Hello, Ryo.\";\n\t\tassertThat(actual).isEqualTo(expected);\n\t}\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">\u52d5\u4f5c\u78ba\u8a8d<\/h3>\n\n\n\n<p>\u30af\u30e9\u30a6\u30c9\u3084\u30b5\u30fc\u30d0\u3067\u7a3c\u50cd\u4e2d\u306e\uff08\u3053\u3053\u3067\u306flocal\u3067bootRun\u3057\u305f\uff09gRPC\u30b5\u30fc\u30d0\u306e\u52d5\u4f5c\u78ba\u8a8d\u65b9\u6cd5\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u3053\u3053\u3067\u306fgrpcurl\u3092\u4f7f\u3063\u3066\u307f\u307e\u3059\u3002<\/p>\n\n\n<p><\/p><div class=\"linkcard\"><div class=\"lkc-external-wrap\"><a class=\"lkc-link no_icon\" href=\"https:\/\/github.com\/fullstorydev\/grpcurl\" target=\"_blank\" rel=\"external noopener\"><div class=\"lkc-card\"><div class=\"lkc-info\"><img loading=\"lazy\" decoding=\"async\" class=\"lkc-favicon\" src=\"https:\/\/www.google.com\/s2\/favicons?domain=github.com\" alt=\"\" width=\"16\" height=\"16\"><div class=\"lkc-domain\">GitHub<\/div>&nbsp;<div class=\"lkc-share\"> <div class=\"lkc-sns-hb\">61 Users<\/div> <div class=\"lkc-sns-po\">251 Pockets<\/div><\/div><\/div><div class=\"lkc-content\"><figure class=\"lkc-thumbnail\"><img decoding=\"async\" class=\"lkc-thumbnail-img\" src=\"\/\/hirabay.net\/wp-content\/uploads\/pz-linkcard\/cache\/5c557f1eac78e4dbcf15bdd5ea2afc20608196f9ab5d328e5d3a19b49525dcbf.jpeg\" alt=\"\"><\/figure><div class=\"lkc-title\"><div class=\"lkc-title-text\">GitHub \u2013 fullstorydev\/grpcurl: Like cURL, but for gRPC: Command-line tool for\u2026<\/div><\/div><div class=\"lkc-url\">https:\/\/github.com\/fullstorydev\/grpcurl<\/div><div class=\"lkc-excerpt\">Like cURL, but for gRPC: Command-line tool for interacting with gRPC servers \u2013 GitHub \u2013 fullstorydev\/grpcurl: Like cURL, but for gRPC: Command-line tool for interacting with gRPC servers<\/div><\/div><div class=\"clear\"><\/div><\/div><\/a><\/div><\/div>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-bash\" data-lang=\"Bash\"><code># \u4e8b\u524d\u306bgrpcurl\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\n# $ brew install grpcurl\n\n$ grpcurl -import-path .\/proto\/src\/main\/proto\/ \\\n  -proto sample.proto \\\n  -plaintext \\\n  -d '{\"name\":\"Ryo\"}' \\\n  localhost:6565 greet.Greet\/greeting\n\n{\n  \"message\": \"Hello, Ryo.\"\n}<\/code><\/pre><\/div>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>\u30aa\u30d7\u30b7\u30e7\u30f3<\/th><th>\u8aac\u660e<\/th><\/tr><\/thead><tbody><tr><td>-import-path<\/td><td>.proto\u30d5\u30a1\u30a4\u30eb\u306e\u5834\u6240\u306e\u6307\u5b9a<\/td><\/tr><tr><td>-proto<\/td><td>.proto\u30d5\u30a1\u30a4\u30eb\u306e\u6307\u5b9a\uff08\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u4e0d\u8981\uff09<\/td><\/tr><tr><td>-plaintext<\/td><td>tls\u3067\u306a\u3044\u6642\u306b\u6307\u5b9a<\/td><\/tr><tr><td>-d<\/td><td>json\u5f62\u5f0f\u3067\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u6307\u5b9a<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-11\">\u30e1\u30c8\u30ea\u30af\u30b9<\/h3>\n\n\n\n<p>\u30b5\u30fc\u30d0\u306e\u30e1\u30c8\u30ea\u30af\u30b9\u306f\u5fc5\u8981\u306a\u4f9d\u5b58\u3055\u3048\u8ffd\u52a0\u3059\u308c\u3070\u81ea\u52d5\u3067\u53ce\u96c6\u3057\u3066\u304f\u308c\u307e\u3059\uff01<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-groovy\" data-file=\"build.gradle\" data-lang=\"Groovy\"><code>dependencies {\n\timplementation 'org.springframework.boot:spring-boot-starter-web'\n\timplementation 'org.springframework.boot:spring-boot-starter-actuator'\n\timplementation \"io.micrometer:micrometer-registry-prometheus\"\n}<\/code><\/pre><\/div>\n\n\n\n<p>\u53ce\u96c6\u3055\u308c\u308b\u30e1\u30c8\u30ea\u30af\u30b9\u306f\u3053\u3093\u306a\u611f\u3058<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-plain\"><code># HELP grpc_server_calls_seconds  \n# TYPE grpc_server_calls_seconds summary\ngrpc_server_calls_seconds_count{method=\"greet.Greet\/greeting\",result=\"OK\",} 1.0\ngrpc_server_calls_seconds_sum{method=\"greet.Greet\/greeting\",result=\"OK\",} 0.024830153\n# HELP grpc_server_calls_seconds_max  \n# TYPE grpc_server_calls_seconds_max gauge\ngrpc_server_calls_seconds_max{method=\"greet.Greet\/greeting\",result=\"OK\",} 0.024830153<\/code><\/pre><\/div>\n\n\n\n<p>\uff08\u30d1\u30fc\u30bb\u30f3\u30bf\u30a4\u30eb\u304c\u898b\u308c\u306a\u305d\u3046\u3067\u6b8b\u5ff5\u2026\uff09<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-12\">TLS<\/h3>\n\n\n\n<p>\u30e1\u30c3\u30bb\u30fc\u30b8\u3092TLS\u3067\u3084\u308a\u3068\u308a\u3059\u308b\u306b\u306f\u3001\u79d8\u5bc6\u9375\u3084\u8a3c\u660e\u66f8\u3092property\u3067\u6307\u5b9a\u3057\u3066\u3042\u3052\u308c\u3070OK\uff01<br>\u30c6\u30b9\u30c8\u7528\u306b\u8a3c\u660e\u66f8\u3092\u81ea\u5206\u3067\u767a\u884c\u3057\u305f\u3044\u5834\u5408\u306f\u4ee5\u4e0b\u304c\u53c2\u8003\u306b\u306a\u308b\u304b\u3068\uff08\u81ea\u5206\u3082\u53c2\u8003\u306b\u3057\u307e\u3057\u305f\uff09<\/p>\n\n\n<p><\/p><div class=\"linkcard\"><div class=\"lkc-external-wrap\"><a class=\"lkc-link no_icon\" href=\"https:\/\/github.com\/grpc\/grpc-java\/blob\/master\/testing\/src\/main\/resources\/certs\/README\" target=\"_blank\" rel=\"external noopener\"><div class=\"lkc-card\"><div class=\"lkc-info\"><img loading=\"lazy\" decoding=\"async\" class=\"lkc-favicon\" src=\"https:\/\/www.google.com\/s2\/favicons?domain=github.com\" alt=\"\" width=\"16\" height=\"16\"><div class=\"lkc-domain\">GitHub<\/div><\/div><div class=\"lkc-content\"><figure class=\"lkc-thumbnail\"><img decoding=\"async\" class=\"lkc-thumbnail-img\" src=\"\/\/hirabay.net\/wp-content\/uploads\/pz-linkcard\/cache\/4023ad3d72608e1ff9d3e695b14b11e9ab007637941cee3ea3fea11932fef63a.jpeg\" alt=\"\"><\/figure><div class=\"lkc-title\"><div class=\"lkc-title-text\">grpc-java\/README at master \u00b7 grpc\/grpc-java<\/div><\/div><div class=\"lkc-url\">https:\/\/github.com\/grpc\/grpc-java\/blob\/master\/testing\/src\/main\/resources\/certs\/README<\/div><div class=\"lkc-excerpt\">The Java gRPC implementation. HTTP\/2 based RPC. Contribute to grpc\/grpc-java development by creating an account on GitHub.<\/div><\/div><div class=\"clear\"><\/div><\/div><\/a><\/div><\/div>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-yaml\" data-file=\"application.yaml\" data-lang=\"Yaml\"><code>grpc:\n  security:\n    private-key: \"file:..\/cert\/server.key\"\n    cert-chain:  \"file:..\/cert\/server.pem\"<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-13\">\u8ca0\u8377\u8a66\u9a13<\/h3>\n\n\n\n<p>\u30b5\u30fc\u30d0\u306b\u5bfe\u3057\u3066\u306e\u8ca0\u8377\u8a66\u9a13\u306e\u3084\u308a\u65b9\u3092\u307e\u3068\u3081\u3066\u304a\u304d\u307e\u3059<\/p>\n\n\n\n<p>\u3053\u3053\u3067\u306fLocust\u3092\u4f7f\u7528\u3057\u307e\u3059\u3002<\/p>\n\n\n<p><\/p><div class=\"linkcard\"><div class=\"lkc-external-wrap\"><a class=\"lkc-link no_icon\" href=\"http:\/\/docs.locust.io\/en\/stable\/testing-other-systems.html#example-writing-a-grpc-user-client\" target=\"_blank\" rel=\"external noopener\"><div class=\"lkc-card\"><div class=\"lkc-info\"><img loading=\"lazy\" decoding=\"async\" class=\"lkc-favicon\" src=\"https:\/\/www.google.com\/s2\/favicons?domain=docs.locust.io\" alt=\"\" width=\"16\" height=\"16\"><div class=\"lkc-domain\">docs.locust.io<\/div>&nbsp;<div class=\"lkc-share\"> <div class=\"lkc-sns-po\">7 Pockets<\/div><\/div><\/div><div class=\"lkc-content\"><figure class=\"lkc-thumbnail\"><img decoding=\"async\" class=\"lkc-thumbnail-img\" src=\"https:\/\/s.wordpress.com\/mshots\/v1\/http%3A%2F%2Fdocs.locust.io%2Fen%2Fstable%2Ftesting-other-systems.html%23example-writing-a-grpc-user-client?w=200\" alt=\"\"><\/figure><div class=\"lkc-title\"><div class=\"lkc-title-text\">Testing other systems\/protocols \u2014 Locust 2.14.2 documentation<\/div><\/div><div class=\"lkc-url\">http:\/\/docs.locust.io\/en\/stable\/testing-other-systems.html#example-writing-a-grpc-user-client<\/div><div class=\"lkc-excerpt\"><\/div><\/div><div class=\"clear\"><\/div><\/div><\/a><\/div><\/div>\n\n\n\n<p>\u307e\u305a\u306f\u74b0\u5883\u69cb\u7bc9\u3067\u3059\u3002\uff08\u8a73\u3057\u304f\u89e6\u308c\u307e\u305b\u3093\ud83d\ude47\u200d\u2642\ufe0f\uff09<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-bash\" data-lang=\"Bash\"><code>$ brew install pyenv\n\n$ brew install pipenv\n\n$ pipenv --python 3.10.3 \n\n$ pipenv install locust\n$ pipenv install grpcio\n$ pipenv install grpcio-tools\n\n$ pipenv shell<\/code><\/pre><\/div>\n\n\n\n<p>\u6b21\u306bgRPC\u306e\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30b3\u30fc\u30c9\u3092\u751f\u6210\u3057\u307e\u3059\u3002<br>gradle\u30bf\u30b9\u30af\u306e<code>generateProto<\/code>\u306b\u4ee3\u308f\u308b\u90e8\u5206\u3067\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-bash\" data-lang=\"Bash\"><code>$ python -m grpc_tools.protoc -I &lt;.proto\u30d5\u30a1\u30a4\u30eb\u914d\u7f6e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea&gt; --python_out=. --grpc_python_out=. &lt;.proto\u30d5\u30a1\u30a4\u30eb\u914d\u7f6e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea&gt;\/sample.proto<\/code><\/pre><\/div>\n\n\n\n<p>\u3059\u308b\u3068&nbsp;<code>sample_pb2.py<\/code>\u3068<code>sample_pb2_grpc.py<\/code>\u304c\u751f\u6210\u3055\u308c\u307e\u3059\uff01<\/p>\n\n\n\n<p>\u3053\u306e\u751f\u6210\u3055\u308c\u305f\u30e2\u30b8\u30e5\u30fc\u30eb\u3092<code>locustfile.py<\/code>\u3067\u4f7f\u7528\u3057\u307e\u3059\u3002<br>\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u304b\u3089\u307b\u307c\u30b3\u30d4\u30da\u3067\u3059\u304c\u3001\u4e00\u65e6\u52d5\u304f\u3082\u306e\u3068\u3057\u3066\u8f09\u305b\u307e\u3059\u3002<br>\uff08\u3069\u3053\u3067\u4f55\u3057\u3066\u3044\u308b\u306e\u304b\u6b63\u76f4\u8ffd\u3048\u3066\u3044\u306a\u3044\u3067\u3059\ud83d\ude07\uff09<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-python\" data-file=\"locustfile.py\" data-lang=\"Python\"><code>import grpc\nimport sample_pb2_grpc\nimport sample_pb2\nfrom locust import events, User, task\nfrom locust.exception import LocustError\nfrom locust.user.task import LOCUST_STATE_STOPPING\nimport gevent\nimport time\n\nimport grpc.experimental.gevent as grpc_gevent\n\ngrpc_gevent.init_gevent()\n\nclass GrpcClient:\n    def __init__(self, environment, stub):\n        self.env = environment\n        self._stub_class = stub.__class__\n        self._stub = stub\n\n    def __getattr__(self, name):\n        func = self._stub_class.__getattribute__(self._stub, name)\n\n        def wrapper(*args, **kwargs):\n            request_meta = {\n                \"request_type\": \"grpc\",\n                \"name\": name,\n                \"start_time\": time.time(),\n                \"response_length\": 0,\n                \"exception\": None,\n                \"context\": None,\n                \"response\": None,\n            }\n            start_perf_counter = time.perf_counter()\n            try:\n                request_meta[\"response\"] = func(*args, **kwargs)\n                request_meta[\"response_length\"] = len(request_meta[\"response\"].message)\n            except grpc.RpcError as e:\n                request_meta[\"exception\"] = e\n            request_meta[\"response_time\"] = (time.perf_counter() - start_perf_counter) * 1000\n            self.env.events.request.fire(**request_meta)\n            return request_meta[\"response\"]\n\n        return wrapper\n\nclass GrpcUser(User):\n    abstract = True\n\n    stub_class = None\n\n    def __init__(self, environment):\n        super().__init__(environment)\n        for attr_value, attr_name in ((self.host, \"host\"), (self.stub_class, \"stub_class\")):\n            if attr_value is None:\n                raise LocustError(f\"You must specify the {attr_name}.\")\n        self._channel = grpc.insecure_channel(self.host)\n        self._channel_closed = False\n        stub = self.stub_class(self._channel)\n        self.client = GrpcClient(environment, stub)\n\n\nclass HelloGrpcUser(GrpcUser):\n    host = \"localhost:6565\"\n    stub_class = sample_pb2_grpc.GreetStub\n\n    @task\n    def greeting(self):\n        if not self._channel_closed:\n            self.client.greeting(sample_pb2.GreetRequest(name=\"Ryo\"))\n        time.sleep(1)<\/code><\/pre><\/div>\n\n\n\n<p>\u6700\u5f8c\u306blocust\u3092\u8d77\u52d5\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p><a rel=\"noreferrer noopener\" href=\"http:\/\/localhost:8089\/\" target=\"_blank\">http:\/\/localhost:8089\/<\/a>&nbsp;\u306b\u30a2\u30af\u30bb\u30b9\u3059\u308b\u3068Locust\u306eUI\u304c\u8868\u793a\u3055\u308c\u307e\u3059\uff01<br>\uff08UI\u306e\u4f7f\u3044\u65b9\u306f\u3053\u3053\u3067\u306f\u7701\u7565\uff09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-14\">gRPC\u30af\u30e9\u30a4\u30a2\u30f3\u30c8<\/h2>\n\n\n\n<p>gRPC\u306e\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u53d7\u3051\u4ed8\u3051\u308b\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u5b9f\u88c5\u3057\u3066\u3044\u304d\u307e\u3059\u3002<br>http\u3067\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u53d7\u3051\u4ed8\u3051\u3066\u3001gRPC\u3067\u30d0\u30c3\u30af\u30dd\u30b9\u30c8\u3059\u308b\u69cb\u6210\u306b\u3057\u3066\u307f\u307e\u3059\u3002<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/hirabay.net\/wp-content\/uploads\/2023\/01\/image-3-1024x328.png\" alt=\"\" class=\"wp-image-194\" width=\"502\" height=\"161\" srcset=\"https:\/\/hirabay.net\/wp-content\/uploads\/2023\/01\/image-3-1024x328.png 1024w, https:\/\/hirabay.net\/wp-content\/uploads\/2023\/01\/image-3-300x96.png 300w, https:\/\/hirabay.net\/wp-content\/uploads\/2023\/01\/image-3-768x246.png 768w, https:\/\/hirabay.net\/wp-content\/uploads\/2023\/01\/image-3-940x301.png 940w, https:\/\/hirabay.net\/wp-content\/uploads\/2023\/01\/image-3.png 1486w\" sizes=\"auto, (max-width: 502px) 100vw, 502px\"><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-15\">\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u4f5c\u6210<\/h3>\n\n\n\n<p><a href=\"https:\/\/start.spring.io\/\" rel=\"noreferrer noopener\" target=\"_blank\">https:\/\/start.spring.io\/<\/a>&nbsp;\u3067\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002<br><code>Spring Web<\/code>\u3092\u4f9d\u5b58\u306b\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u30c0\u30a6\u30f3\u30ed\u30fc\u30c9\uff06\u89e3\u51cd\u5f8c\u3001<code>build.gradle<\/code>\u3092\u4fee\u6b63\u3057\u307e\u3059<br>\uff08\u4fee\u6b63\u90e8\u5206\u306e\u307f\u629c\u7c8b\uff09<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-groovy\" data-file=\"build.gradle\" data-lang=\"Groovy\"><code>\/\/ \u30d7\u30e9\u30b0\u30a4\u30f3\u306e\u8ffd\u52a0\nplugins {\n    id \"io.github.lognet.grpc-spring-boot\" version '4.6.0'\n}\n\nrepositories {\n\tmavenCentral()\n\tmavenLocal() \/\/ local repository\u5229\u7528\n}\n\ndependencies {\n    \/\/ \u5148\u307b\u3069upload\u3057\u305fproto\u306e\u53d6\u308a\u8fbc\u307f\n\timplementation 'rhirabay:proto:+'\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">gRPC\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u5b9f\u88c5<\/h3>\n\n\n\n<p>gRPC\u30b5\u30fc\u30d0\u3068\u306e\u901a\u4fe1\u306b\u5fc5\u8981\u306astub\uff08web mvc\u3067\u3044\u3046RestTemplate\uff09\u3092Bean\u767b\u9332\u3057\u3066\u304a\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>import io.grpc.ManagedChannel;\nimport io.grpc.ManagedChannelBuilder;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport rhirabay.grpc.sample.GreetGrpc;\n\n@Configuration\npublic class GrpcAutoConfiguration {\n    @Bean\n    ManagedChannel managedChannel() {\n        return ManagedChannelBuilder.forAddress(\"localhost\", 6565)\n                .usePlaintext()  \/\/ TLS\u3092\u5229\u7528\u3057\u306a\u3044\u5834\u5408\n                .build();\n    }\n\n    @Bean\n    GreetGrpc.GreetBlockingStub greetBlockingStub(ManagedChannel managedChannel) {\n        return GreetGrpc.newBlockingStub(managedChannel);\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p>\u30b9\u30bf\u30d6\u306e\u30af\u30e9\u30b9\u306f.proto\u306e\u5b9a\u7fa9\u30d5\u30a1\u30a4\u30eb\u3068\u5bfe\u5fdc\u3057\u3066\u3044\u3066\u3001<br><code>&lt;service\u540d&gt;Grpc.&lt;service\u540d&gt;BlockingStub<\/code><br>\u3068\u3044\u3046\u547d\u540d\u3067\u3059\u3002<\/p>\n\n\n\n<p>\u6b21\u306bstub\u3092\u7528\u3044\u3066\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u30af\u30e9\u30b9\u3092\u5b9f\u88c5\u3057\u307e\u3059<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>import lombok.RequiredArgsConstructor;\nimport org.springframework.stereotype.Component;\nimport rhirabay.grpc.sample.GreetGrpc;\nimport rhirabay.grpc.sample.GreetRequest;\n\n@Component\n@RequiredArgsConstructor\npublic class SampleClient {\n    private final GreetGrpc.GreetBlockingStub greetBlockingStub;\n\n    public String greeting(String name) {\n        var request = GreetRequest.newBuilder()\n                .setName(name)\n                .build();\n        var response = this.greetBlockingStub.greeting(request);\n        return response.getMessage();\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<p>\u30ea\u30af\u30a8\u30b9\u30c8\u30fb\u30ec\u30b9\u30dd\u30f3\u30b9\u306e\u30e2\u30c7\u30eb\u30af\u30e9\u30b9\u306f\u3053\u308c\u3082.proto\u30d5\u30a1\u30a4\u30eb\u3067\u5b9a\u7fa9\u3057\u305f\u3082\u306e\u3068\u5bfe\u5fdc\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u751f\u6210\u306fBuiler\u30d1\u30bf\u30fc\u30f3\u3067\u3001\u76f4\u306e\u53c2\u7167\u306fgetter\u3067\u3068\u3044\u3046\u611f\u3058<\/p>\n\n\n\n<p>\u6700\u5f8c\u306bHTTP\u3067\u30ea\u30af\u30a8\u30b9\u30c8\u3092\u53d7\u3051\u53d6\u308bRestController\u3092\u5b9f\u88c5\u3057\u307e\u3059\uff08\u3053\u3053\u306fgRPC\u8981\u7d20\u306a\u3057\uff09<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>import lombok.RequiredArgsConstructor;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\nimport rhirabay.grpc.client.SampleClient;\n\n@RestController\n@RequiredArgsConstructor\npublic class SampleController {\n    private final SampleClient sampleClient;\n    private final TlsSampleClient tlsSampleClient;\n\n    @GetMapping(\"\/greeting\")\n    public String greeting(@RequestParam(defaultValue = \"anonymous\", required = false) String name) {\n        return sampleClient.greeting(name);\n    }\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-17\">\u5358\u4f53\u30c6\u30b9\u30c8<\/h3>\n\n\n\n<p>gRPC\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u5358\u4f53\u30c6\u30b9\u30c8\u3092\u5b9f\u88c5\u3057\u307e\u3059\u3002<br>gRPC\u30b5\u30fc\u30d0\u3092\u30c6\u30b9\u30c8\u5185\u3067\u8d77\u52d5\u3057\u3001\u3061\u3083\u3093\u3068\u30b5\u30fc\u30d0\u3068\u901a\u4fe1\u3067\u304d\u308b\u304b\u3069\u3046\u304b\u30c6\u30b9\u30c8\u3057\u307e\u3059\u3002<br>\u5185\u5bb9\u3068\u3057\u3066\u306f<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30b5\u30fc\u30d0\u3067\u53d7\u3051\u53d6\u3063\u305f\u30ea\u30af\u30a8\u30b9\u30c8\uff08\u60f3\u5b9a\u901a\u308a\u30ea\u30af\u30a8\u30b9\u30c8\u304c\u3067\u304d\u3066\u3044\u308b\u306e\u304b\uff1f\uff09<\/li>\n\n\n\n<li>\u30e1\u30bd\u30c3\u30c9\u306e\u8fd4\u308a\u5024\uff08\u60f3\u5b9a\u901a\u308a\u30b5\u30fc\u30d0\u306e\u30ec\u30b9\u30dd\u30f3\u30b9\u3092\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0\u3067\u304d\u3066\u3044\u308b\u306e\u304b\uff1f\uff09<\/li>\n<\/ul>\n\n\n\n<p>\u304c\u691c\u8a3c\u3067\u304d\u308c\u3070\u3044\u3044\u306f\u305a<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>@ExtendWith(MockitoExtension.class)\nclass SampleClientTest {\n    private SampleClient sampleClient;\n\n    static String UNIQUE_SERVER_NAME = \"server^name\";\n\n    private static MutableHandlerRegistry serviceRegistry = new MutableHandlerRegistry();\n    private static Server inProcessServer = InProcessServerBuilder\n            .forName(UNIQUE_SERVER_NAME)\n            .fallbackHandlerRegistry(serviceRegistry)\n            .directExecutor()\n            .build();\n\n    @Spy\n    private GreetGrpcMock greetGrpcMock = new GreetGrpcMock();\n\n    @BeforeAll\n    @SneakyThrows\n    static void startServer() {\n        inProcessServer.start();\n    }\n\n    @AfterAll\n    static void shutdownServer() {\n        inProcessServer.shutdownNow();\n    }\n\n    @BeforeEach\n    void setup() {\n        var inProcessChannel = InProcessChannelBuilder\n                .forName(UNIQUE_SERVER_NAME)\n                .directExecutor()\n                .build();\n\n        serviceRegistry.addService(greetGrpcMock);\n        var stub = GreetGrpc.newBlockingStub(inProcessChannel);\n        sampleClient = new SampleClient(stub);\n    }\n\n    @Test\n    void test() {\n        \/\/ gRPC\u30b5\u30fc\u30d3\u30b9\u306e\u52d5\u4f5c\u3092\u5b9a\u7fa9\n        doAnswer(invocation -&gt; {\n            \/\/ \u30ea\u30af\u30a8\u30b9\u30c8\u3092\u691c\u8a3c\u3059\u308b\uff08\u3053\u3053\u3067\u5b9f\u88c5\u3059\u308b\u306e\u3082\u3069\u3046\u304b\u3068\u601d\u3046\u304c\u2026\uff09\n            var request = (GreetRequest)(invocation.getArgument(0));\n            assertThat(request.getName()).isEqualTo(\"test\");\n\n            var responseObserver = (StreamObserver&lt;GreetResponse&gt;)(invocation.getArgument(1));\n            GreetResponse response = GreetResponse.newBuilder()\n                    .setMessage(\"Hello, client test.\")\n                    .build();\n            responseObserver.onNext(response);\n            responseObserver.onCompleted();\n\n            return null;\n        }).when(greetGrpcMock).greeting(any(), any());\n\n        \/\/ \u30c6\u30b9\u30c8\u5bfe\u8c61\u306e\u30e1\u30bd\u30c3\u30c9\u547c\u3073\u51fa\u3057\u3068\u691c\u8a3c\n        var actual = sampleClient.greeting(\"test\");\n        var expected = \"Hello, client test.\";\n        assertThat(actual).isEqualTo(expected);\n    }\n\n    \/\/ spy\u5316\u306e\u305f\u3081\u306bgRPC\u30b5\u30fc\u30d3\u30b9\u30af\u30e9\u30b9\u3092\u5b9a\u7fa9\n    static class GreetGrpcMock extends GreetGrpc.GreetImplBase {}\n}<\/code><\/pre><\/div>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">TLS<\/h3>\n\n\n\n<p>\u30b5\u30fc\u30d0\u3068\u306e\u901a\u4fe1\u3092TLS\u3067\u884c\u3044\u305f\u3044\u6642\u306e\u5b9f\u88c5\u65b9\u6cd5\u3067\u3059<br><code>ManagedChannel<\/code>\u3060\u3051\u66f8\u304d\u63db\u3048\u307e\u3059<\/p>\n\n\n\n<div class=\"hcb_wrap\"><pre class=\"prism undefined-numbers lang-java\" data-lang=\"Java\"><code>    @Bean\n    @SneakyThrows\n    ManagedChannel managedChannel(GrpcProperties grpcProperties) {\n        var channelBuilder = ManagedChannelBuilder.forAddress(\"localhost\", 6565);\n        var certChain = new FileUrlResource(\"..\/cert\/server.pem\");\n        var sslContext = GrpcSslContexts.forClient().trustManager(certChain.getInputStream()).build();\n        return ((NettyChannelBuilder)channelBuilder)\n                .useTransportSecurity()\n                .sslContext(sslContext)\n                .build();\n    }<\/code><\/pre><\/div>\n","protected":false},"excerpt":{"rendered":"<p>gRPC\u3092SpringBoot\u3067\u5b9f\u88c5\u3059\u308b\u6a5f\u4f1a\u304c\u3042\u308a\u307e\u3057\u305f\u3002 \u3044\u308d\u3044\u308d\u306a\u30b5\u30a4\u30c8\u304c\u3042\u308b\u306e\u3067\u3059\u304c\u3001\u696d\u52d9\u3067\u3084\u308d\u3046\u3068\u3059\u308b\u3053\u3068\u3092\u3059\u3079\u3066\u7406\u89e3\u3059\u308b\u306b\u306f\u3042\u3061\u3053\u3061\u3092\u63a2\u3057\u56de\u308b\u5fc5\u8981\u304c\u3042\u3063\u3066\u5927\u5909\u3067\u3057\u305f\u3002\u3002\u3002 \u305d\u3093\u306a\u7d4c\u9a13\u304b\u3089\u3001\u3053\u306e\u8a18\u4e8b\u3067\u306f\u5b9f\u52d9\u3067\u6c17\u306b &#8230; <\/p>\n","protected":false},"author":1,"featured_media":196,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[44,45,13],"class_list":{"0":"post-189","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-6","8":"tag-grpc","9":"tag-lognet","10":"tag-springboot"},"jetpack_featured_media_url":"https:\/\/hirabay.net\/wp-content\/uploads\/2023\/01\/SpringBoot_grpc.png","_links":{"self":[{"href":"https:\/\/hirabay.net\/index.php?rest_route=\/wp\/v2\/posts\/189","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hirabay.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hirabay.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hirabay.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hirabay.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=189"}],"version-history":[{"count":7,"href":"https:\/\/hirabay.net\/index.php?rest_route=\/wp\/v2\/posts\/189\/revisions"}],"predecessor-version":[{"id":200,"href":"https:\/\/hirabay.net\/index.php?rest_route=\/wp\/v2\/posts\/189\/revisions\/200"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/hirabay.net\/index.php?rest_route=\/wp\/v2\/media\/196"}],"wp:attachment":[{"href":"https:\/\/hirabay.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=189"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hirabay.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=189"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hirabay.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=189"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}