从微信小程序到微服务:一个客户端开发的Spring Cloud入门血泪史

悲观锁诗人
2025-12-24 08:37
阅读 312

上周五晚上十一点,我还在工位上盯着VSCode里一堆红红的报错发呆。产品经理突然在群里@我说:“这个需求下周上线,后端接口还没对齐?你们后端是不是又在摸鱼?”——可问题是,这项目压根没配后端!领导临时拍板让我这个写了三年微信小程序的客户端“顺便搞个微服务”,理由是:“你不是会写代码嘛,Java不就是换个语法?”

行吧,谁让我在杭州,阿里网易隔壁坐一排猎头天天问“要不要试试后端机会”。为了简历不那么单薄,我咬牙开了Spring Cloud的坑。今天这篇文章,就是记录我从零搭建第一个微服务系统时踩过的雷、熬过的夜,以及那些让我想砸键盘的瞬间。


为什么客户端要碰微服务?

先说清楚我的背景:腾讯干了三年客户端,主力是微信小程序,日常和WXML、setData()、onPullDownRefresh()打交道。工具链基本锁定VSCode + Prettier + ESLint + Remote SSH(远程连测试机)。数据库?那是DBA的事;部署?那是运维的锅。

但最近团队接了个新项目:要做一个综合型内容聚合平台,不仅要展示资讯,还要对接第三方数据源——比如实时抓取某些网站的更新(没错,就是爬虫那套活)。前端用小程序没问题,但后端需要:

  • 独立的数据采集服务(避免阻塞主业务)
  • 用户行为分析模块
  • 内容审核与缓存层

架构师甩给我一张PPT:“用Spring Cloud,拆成几个微服务,高内聚低耦合。” 我心里一万个草泥马奔腾而过——我连Eureka是什么都不知道!

但转念一想:现在大模型这么火,AI相关岗位基本都要求懂点后端架构。学!必须学!


第一步:别被“微服务”吓住

很多人一听“微服务”就觉得高大上,其实核心思想就一条:把一个大应用拆成一堆小应用,各干各的活,通过网络互相调用

类比小程序开发:以前所有逻辑写在一个Page里,后来我们拆Component、拆Utils、拆Store。微服务就是把这个思路放大到进程级别——每个服务跑在自己的JVM里,通过HTTP或RPC通信。

我选Spring Cloud是因为生态成熟,文档多(虽然有些已经过时),而且我们公司内部很多老系统就是基于它建的,方便“借鉴”(抄)。


搭建骨架:注册中心不能少

微服务第一个要解决的问题是:服务怎么找到彼此?

想象一下:用户服务要调用订单服务,但订单服务可能部署在10台机器上,IP随时变。总不能写死IP吧?这时候就需要服务注册与发现

我用了 Eureka —— Netflix开源的老将,Spring Cloud全家桶默认集成。

# eureka-server/src/main/resources/application.yml
server:
  port: 8761

eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

启动后访问 http://localhost:8761,看到那个熟悉的蓝色界面,我差点感动哭出来——终于有个东西能跑了!

然后让其他服务注册进来:

# user-service/application.yml
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

⚠️ 坑点:本地开发时如果开多个服务,记得改 instance-id 或关掉 prefer-ip-address,不然Eureka会把所有实例识别成同一个!


服务调用:Feign真香,但别乱用

服务之间怎么通信?最简单的是用 RestTemplate 手动拼URL,但太low。Spring Cloud推荐用 OpenFeign —— 声明式HTTP客户端。

比如我在用户服务里调用内容服务:

@FeignClient(name = "content-service")
public interface ContentClient {
    @GetMapping("/api/v1/articles/{id}")
    Article getArticle(@PathVariable("id") Long id);
}

Controller里直接@Autowired注入,像调本地方法一样用。爽!

但注意:Feign默认不支持超时重试,线上一旦下游慢,你的线程池就炸了。务必配超时:

feign:
  client:
    config:
      default:
        connectTimeout: 2000
        readTimeout: 5000

另外,别在循环里调Feign!我第一次写了个批量查询,for循环里调100次,结果Hystrix熔断直接触发,服务雪崩。后来改成用 /batch 接口一次拉完——接口设计真的很重要。


配置管理:别再硬编码了!

以前写小程序,配置都放 config.js,改个API地址要重新打包。微服务更惨:几十个服务,每个都要改?

Spring Cloud Config 来救场。我把所有配置扔到Git仓库,服务启动时自动拉取:

# bootstrap.yml
spring:
  application:
    name: user-service
  cloud:
    config:
      uri: http://config-server:8888

配合 Spring Cloud Bus + RabbitMQ,还能实现配置热更新——改完Git,所有服务自动刷新。再也不用半夜被叫起来重启服务了(虽然运维还是骂我乱改配置)。


熔断与限流:保住底线

去年双11,我们小程序因为第三方接口超时,导致整个首页白屏。这次我学乖了:微服务必须有熔断机制

Resilience4j(Spring Cloud官方已弃用Hystrix,别踩坑!):

@CircuitBreaker(name = "contentService", fallbackMethod = "getDefaultArticle")
public Article getArticle(Long id) {
    return contentClient.getArticle(id);
}

private Article getDefaultArticle(Long id, Exception ex) {
    return new Article("默认文章", "暂无内容");
}

同时配上 Sentinel 做限流。比如爬虫服务,每秒最多请求5次,防止被目标网站封IP。规则可以动态调整,不用重启。


关于“Go”和“爬虫”的插曲

说到爬虫,其实我一开始想用 Go 写数据采集服务——毕竟Go并发强、内存占用低,写爬虫很合适。但团队技术栈全是Java,领导一句“统一语言”就把我否了。

不过我还是偷偷研究了下:用Go写个轻量爬虫,部署成独立服务,通过gRPC和Java主服务通信。性能确实猛,1核2G机器能跑500+协程。但考虑到日志、监控、链路追踪都要重新搭,最后还是妥协用了Java + WebMagic。

但这段经历让我意识到:技术选型不是越新越好,而是看团队能否Hold住。微服务拆得再漂亮,没人维护也是废铁。


综合对比:几种常见微服务组件

功能 Spring Cloud Netflix (旧) Spring Cloud Alibaba 纯手动方案
注册中心 Eureka Nacos 自建ZooKeeper
配置中心 Config Server Nacos Git + 轮询
熔断 Hystrix (已停更) Sentinel 手写状态机
网关 Zuul Spring Cloud Gateway Nginx + Lua
链路追踪 Sleuth + Zipkin SkyWalking 手打日志

我现在用的是 Spring Cloud Alibaba 全家桶(Nacos + Sentinel + Gateway),国内文档全,阿里系兼容性好,在杭州找工作也加分(笑)。


生产环境教训:别信“本地跑得好好的”

本地一切正常,一上K8s就崩?太常见了!

  • 时区问题:Docker镜像默认UTC,数据库存的时间差8小时。加 -Duser.timezone=Asia/Shanghai
  • 健康检查:K8s的liveness probe路径没配,Pod反复重启。记得暴露 /actuator/health
  • 日志丢失:没挂ELK,出问题只能ssh进容器翻log。现在强制要求所有服务接入公司日志平台

最惨一次:忘了关Swagger,线上暴露了所有内部接口。安全组连夜拉黑我IP……从此 spring.profiles.active=prod 必带 swagger.enable=false


写在最后:客户端转后端,值不值?

折腾两个月,系统终于上线了。虽然QPS只有200(被同事嘲笑“还不如单体”),但至少没挂。更重要的是,我理解了:

  • 为什么小程序加载慢可能是后端没做缓存
  • 为什么接口要设计幂等
  • 为什么运维总说“别在高峰期发版”

如果你也在做客户端,建议至少了解微服务基础。不是为了转岗,而是打通全链路视角。下次和后端吵架时,你至少能说:“你这个Feign超时设太短了,应该参考RTT+P99。”

至于AI?我还在学LangChain,打算用微服务封装向量检索和LLM调用。说不定下篇文章就叫《用Spring Cloud搭建AI Agent网关》?

哦对了,标题我特意没用冒号——程序员写博客,就得有点叛逆精神,对吧?

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝