Golang 微服务对接 Spring-Cloud Gateway
- 2024-03-07 江苏
本文字数:10069 字
阅读完需:约 33 分钟

最近接了一个需求,要把一些现有的 golang 微服务对接到老平台的 spring cloud 微服务框架中。这些 golang 微服务提供了一些 proto+grpc 接口,对接老平台目的就是,想要快速复用这些后端的业务能力,这样一来,只需要涉及交互的设计和前端编码的工作,后端不需要用 java 重写一遍造轮子,并且这些 golang 微服务是之前上过线的,所以稳定性和准确性都有保证。
老平台的架构和这个极精简版类似:
所以,我就把重心放在如何将 golang 微服务接入到 spring cloud gateway 里,然后要满足以下几个需求:
复用 spring cloud gateway 路由和负载均衡能力,能将 url 正确路由到 golang 微服务内,当然前提是 golang 微服务需要暴露出 restful api
复用 spring cloud gateway 的身份认证能力
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/hello3. 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
版权声明: 本文为 InfoQ 作者【于顾而言】的原创文章。
原文链接:【http://xie.infoq.cn/article/ec3a5e5811f65be0989e8e83e】。文章转载请联系作者。
于顾而言
Life-long Learning & Loving 2022-09-10 加入
深信服 | 高级后台开发工程师 中国电信 | 高级安全研发工程师 南京理工大学 | 光学工程本硕 专注云安全领域6年,SASE & 零信任都懂一点 发点文章就违规,已经快没热情了,不会再更新了~~~







评论