写点什么

Golang 微服务对接 Spring-Cloud Gateway

作者:于顾而言
  • 2024-03-07
    江苏
  • 本文字数:10069 字

    阅读完需:约 33 分钟

Golang微服务对接Spring-Cloud Gateway

最近接了一个需求,要把一些现有的 golang 微服务对接到老平台的 spring cloud 微服务框架中。这些 golang 微服务提供了一些 proto+grpc 接口,对接老平台目的就是,想要快速复用这些后端的业务能力,这样一来,只需要涉及交互的设计和前端编码的工作,后端不需要用 java 重写一遍造轮子,并且这些 golang 微服务是之前上过线的,所以稳定性和准确性都有保证。


老平台的架构和这个极精简版类似:


所以,我就把重心放在如何将 golang 微服务接入到 spring cloud gateway 里,然后要满足以下几个需求:


  1. 复用 spring cloud gateway 路由和负载均衡能力,能将 url 正确路由到 golang 微服务内,当然前提是 golang 微服务需要暴露出 restful api

  2. 复用 spring cloud gateway 的身份认证能力

  3. java 和 golang 微服务可以互相进行 rpc 调用,比如 golang 微服务可以通过 rpc 获取某个租户的信息


通过在网上的一番调研,最终锁定了 spring-cloud-alibaba-sidecar 和 grpc-gateway 这两个组件,整体的对接思路如下,下面开始搞个 demo 验证一下:



1. Spring Cloud Gateway 环境搭建

1.1 mvn 安装

wget https://dlcdn.apache.org/maven/maven-3/3.9.6/binaries/apache-maven-3.9.6-bin.tar.gztar -zxvf apache-maven-3.9.6-bin.tar.gzvim /etc/profile/*    尾部追加    export MAVEN_HOME=/usr/local/apache-maven-3.9.6    export PATH=$MAVEN_HOME/bin:$PATH*/
source /etc/profile mvn -v/* Apache Maven 3.9.6 (bc0240f3c744dd6b6ec2920b3cd08dcc295161ae) Maven home: /usr/download/apache-maven-3.9.6 Java version: 21.0.2, vendor: Oracle Corporation, runtime: /usr/lib/jvm/jdk-21-oracle-x64 Default locale: en_US, platform encoding: UTF-8 OS name: "linux", version: "3.10.0-1160.el7.x86_64", arch: "amd64", family: "unix"*/
vim conf/settings.xml/* <!-- mirror标签页下新增 <mirror> <id>huaweicloud</id> <mirrorOf>central</mirrorOf> <name>huaweicloud</name> <url>https://mirrors.huaweicloud.com/repository/maven/</url> </mirror>*/
复制代码


1.2 jdk 安装

wget https://download.oracle.com/java/21/latest/jdk-21_linux-x64_bin.rpmrpm -ivh jdk-21_linux-x64_bin.rpmjavac -version/*javac 21.0.2*/
java --version/*java 21.0.2 2024-01-16 LTSJava(TM) SE Runtime Environment (build 21.0.2+13-LTS-58)Java HotSpot(TM) 64-Bit Server VM (build 21.0.2+13-LTS-58, mixed mode, sharing)*/
复制代码


1.3 spring cloud gateway

git clone git@github.com:spring-guides/gs-gateway.gitcd gs-gateway/initialvim pom.xml/*pom修改如下:<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">        <modelVersion>4.0.0</modelVersion>        <parent>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-starter-parent</artifactId>                <version>3.2.0</version>                <relativePath/> <!-- lookup parent from repository -->        </parent>        <groupId>com.example</groupId>        <artifactId>gs-gateway</artifactId>        <version>0.0.1-SNAPSHOT</version>        <name>gs-gateway</name>        <description>Demo project for Spring Boot</description>        <properties>                <java.version>17</java.version>                <spring-cloud.version>2023.0.0-RC1</spring-cloud.version>        </properties>        <dependencies>                <dependency>                        <groupId>org.springframework.cloud</groupId>                        <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>                </dependency>                <dependency>                        <groupId>org.springframework.cloud</groupId>                        <artifactId>spring-cloud-starter-gateway</artifactId>                </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-stub-runner</artifactId> <scope>test</scope> </dependency>
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency>
</dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency>
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2022.0.0.0-RC1</version> <type>pom</type> <scope>import</scope> </dependency>
</dependencies> </dependencyManagement>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.9.0</version> <configuration> <source>2.1</source> <target>2.1</target> <verbose>true</verbose> </configuration> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
</project>*/
mvn installjava -jar gs-gateway-0.0.1-SNAPSHOT.jar --debugcurl http://localhost:8080/get/*{ "args": {}, "headers": { "Accept": "*/*", "Connection": "close", "Forwarded": "proto=http;host=\"localhost:8080\";for=\"0:0:0:0:0:0:0:1:56207\"", "Hello": "World", "Host": "httpbin.org", "User-Agent": "curl/7.54.0", "X-Forwarded-Host": "localhost:8080" }, "origin": "0:0:0:0:0:0:0:1, 73.68.251.70", "url": "http://localhost:8080/get"}*/
复制代码

2. Nacos 安装

wget https://github.com/alibaba/nacos/releases/download/2.3.0/nacos-server-2.3.0.tar.gztar -zxvf nacos-server-2.3.0.tar.gzbin/startup.sh -m standalone
复制代码



3. Golang 和 Java 启动 web 服务

mvn archetype:generatevim pom.xml/*修改如下:<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">        <modelVersion>4.0.0</modelVersion>        <parent>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-starter-parent</artifactId>                <version>3.2.0</version>                <relativePath/> <!-- lookup parent from repository -->        </parent>        <groupId>javaweb</groupId>        <artifactId>javaweb</artifactId>        <version>0.0.1-SNAPSHOT</version>        <name>javaweb</name>        <description>Demo project for Spring Boot</description>        <properties>                <java.version>17</java.version>                <spring-cloud.version>2023.0.0-RC1</spring-cloud.version>        </properties>        <dependencies>                <dependency>                       <groupId>junit</groupId>                       <artifactId>junit</artifactId>                       <version>4.12</version>                       <scope>test</scope>               </dependency>
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.6.3</version> </dependency>

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-contract-stub-runner</artifactId> <scope>test</scope> </dependency>
</dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency>
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2022.0.0.0-RC1</version> <type>pom</type> <scope>import</scope> </dependency>
</dependencies> </dependencyManagement>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.6.3</version> </plugin> </plugins> </build> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
</project>*/
vim bootstrap.yml/*新增如下:server: port: 10001
spring: profiles: active: dev application: name: javaweb cloud: nacos: config: file-extension: yaml group: dev server-addr: 127.0.0.1:8848 discovery: auto-register: true server-addr: 127.0.0.1:8848 locator: enabled: true lower-case-service-id: true*/
vim App.java/*修改java文件如下:package javaweb;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;import org.springframework.context.annotation.Bean;
@EnableDiscoveryClient@RestController@RequestMapping("/java-service-1")@SpringBootApplicationpublic class App {
public static void main(String[] args) { SpringApplication.run(App.class, args); }
@GetMapping("/hello") public String hello() { return "[java]Hello, World!we server in port 10001"; }
@Bean public TomcatServletWebServerFactory servletContainer(){ return new TomcatServletWebServerFactory(8022) ; }}*/
java -jar target/javaweb-0.0.1-SNAPSHOT.jar --spring.config.location=/usr/code/javaweb/bootstrap.yml --spring.cloud.nacos.config.import-check.enabled=falsecurl http://localhost:10001/java-service-1/hello
复制代码



wget https://golang.google.cn/dl/go1.21.6.darwin-amd64.tar.gztar -zxvf go1.21.6.linux-amd64.tar.gz -C /usr/local/vim /etc/profile/*尾部追加:export GOROOT=/usr/local/goexport PATH=$GOPATH/bin:$GOROOT/bin:$PATH*/
source /etc/profile
go version/*go version go1.21.6 linux/amd64*/
vi main.go/*新建main.go如下:package main
import ( "encoding/json" "fmt" "log" "net/http")
func main() { http.HandleFunc("/golang-service/hello", helloHandler) http.HandleFunc("/golang-service/health", healthHandler) log.Println("Go 微服务已启动,监听端口 10002...") log.Fatal(http.ListenAndServe(":10002", nil))}
func helloHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "[golang] hello world!")}
func healthHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") actuator := make(map[string]string) actuator["status"] = "UP" _ = json.NewEncoder(w).Encode(actuator)
log.Println("[golang] i'm alive!...")}
*/go run main.go//2024/02/03 10:43:21 Go 微服务已启动,监听端口 10002...curl http://localhost:10002/golang-service/hello
复制代码


3. Alibaba Sidecar

git clone git@github.com:alibaba/spring-cloud-alibaba.git
cd spring-cloud-alibaba/spring-cloud-alibaba-examples/spring-cloud-alibaba-sidecar-examples/spring-cloud-alibaba-sidecar-nacos-example/
vi src/main/resources/application.yml/*server: port: 8070spring: cloud: nacos: username: 'nacos' password: 'nacos' discovery: server-addr: 127.0.0.1:8848 group: DEFAULT_GROUP gateway: discovery: locator: enabled: true loadbalancer: nacos: enabled: true ribbon: enabled: false
application: name: golangwebsidecar: # 异构微服务的IP ip: 127.0.0.1 # 异构微服务的端口 port: 10002
# 异构微服务的健康检查URL health-check-url: http://localhost:10002/golang-service/healthmanagement: endpoint: health: show-details: always*/
mvn install
java -jar target/spring-cloud-alibaba-sidecar-nacos-example-2022.0.0.0.jar
复制代码




大家注意看这个 10002 是 golang 微服务的端口,心跳检查也持续进行,灰常完美。



4. Gateway 路由配置修改

# vim bootstrap.ymlserver:  port: 10003
spring: profiles: active: dev application: name: gy-gateway
cloud: gateway: discovery: auto-register: true server-addr: 127.0.0.1:8848 locator: enabled: true # 是否使用service-id的小写,默认是大写 lower-case-service-id: true routes: - id: javawebsvr uri: lb://javaweb predicates: - Path=/java-service-1/** # 断言,路径相匹配的进行路由(注意**为通配符) filters: - StripPrefix=1 - id: golangsvr # uri: http://127.0.0.1:10002/ 都行 uri: lb://golangweb predicates: - Path=/golang-service/** # 断言,路径相匹配的进行路由(注意**为通配符) filters: - StripPrefix=1curl http://localhost:10003/golang-service/golang-service/hellocurl http://localhost:10003/java-service-1/java-service-1/hello
复制代码



5. Java 调用 Golang 微服务

在之前的javaweb工程的基础上改了一些东西:vi bootstrap.yml/*server:  port: 10011*/
vim App.java/*package javaweb;
import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.web.client.RestTemplate;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Bean;import org.springframework.cloud.client.loadbalancer.LoadBalanced;import org.springframework.cloud.client.discovery.DiscoveryClient;import org.springframework.cloud.client.ServiceInstance;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import java.util.List;
@EnableDiscoveryClient@RestController@RequestMapping("/java-service-1")@SpringBootApplicationpublic class App {
public static void main(String[] args) { SpringApplication.run(App.class, args); }
@GetMapping("/hello") public String hello() { return "[java]Hello, World!we server in port 10001"; }
@Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); }
@Autowired private RestTemplate restTemplate;
@Autowired private DiscoveryClient discoveryClient;
@GetMapping("/hellogolang") public String hellogolang() { List<String> services = discoveryClient.getServices();
for (String service : services) { System.out.println("**service**:"+service); } List<ServiceInstance> instances = discoveryClient.getInstances("golangweb");
for (ServiceInstance instance : instances) {
System.out.println(instance.getInstanceId()+"\t"+instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri()); String url = "http://"+instance.getHost() + ":" + instance.getPort() + "/golang-service/hello"; return restTemplate.getForObject(url, String.class); } return "ha";
}}*/
java -jar target/javaweb-0.0.1-SNAPSHOT.jar --spring.config.location=/usr/code/javaweb/bootstrap.yml --spring.cloud.nacos.config.import-check.enabled=false --debug --spring.main.allow-circular-references=true --spring.main.web-application-type=reactive
复制代码



6. Reference

https://sca.aliyun.com/zh-cn/blog/spring-boot-to-spring-cloud-best-practice

https://blog.csdn.net/lucky_ykcul/article/details/105219891

https://blog.csdn.net/it_sunwz/article/details/115271506

https://blog.csdn.net/u011019141/article/details/78458566

https://blog.csdn.net/zsf_join/article/details/99819845

https://github.com/spring-guides/gs-gateway

https://spring.io/guides/gs/gateway/

https://www.jianshu.com/p/c4952ef14660

https://blog.csdn.net/llm_hao/article/details/122856895

https://blog.csdn.net/weixin_44102521/article/details/117689297

https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html

https://javahungry.blogspot.com/2019/05/solved-no-main-manifest-attribute-in-jar.html

https://blog.csdn.net/zsf_join/article/details/99819845

https://blog.csdn.net/hkl_Forever/article/details/129353742

https://blog.csdn.net/m4330187/article/details/122182282

https://juejin.cn/post/6844903999439634446

https://blog.csdn.net/m0_50717367/article/details/118559024

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

于顾而言

关注

Life-long Learning & Loving 2022-09-10 加入

深信服 | 高级后台开发工程师 中国电信 | 高级安全研发工程师 南京理工大学 | 光学工程本硕 专注云安全领域6年,SASE & 零信任都懂一点 发点文章就违规,已经快没热情了,不会再更新了~~~

评论

发布
暂无评论
Golang微服务对接Spring-Cloud Gateway_golang_于顾而言_InfoQ写作社区