本文基于 Camel 3.2.0 进行实践
前言
最近本人在研究 Camel 相关技术,现在有个问题,Camel 如何接入已有的微服务架构的系统中,进行服务发现并通过 REST 调用各项服务?
Apache Camel Spring Boot Starters 官方文档:
https://camel.apache.org/camel-spring-boot/latest/index.html
组件 spring-cloud-netflix 官方文档:
https://camel.apache.org/camel-spring-boot/latest/spring-cloud-netflix.html
Camel 官方文档对 Spring Cloud 这块的内容不是很详细,只是粗略描述。
使用方式
使用 Camel Spring Boot Starter
如果要接入 Spring Cloud 体系,首先,Camel 应用要基于 Spring Boot 启动。
引入相关依赖
本文实践版本:
Camel Spring Cloud + Eureka 相关依赖:
implementation "org.apache.camel.springboot:camel-service-starter"
implementation "org.apache.camel.springboot:camel-spring-cloud-starter"
implementation "org.apache.camel.springboot:camel-spring-cloud-netflix-starter"
implementation "org.apache.camel.springboot:camel-ribbon-starter"
implementation "org.springframework.cloud:spring-cloud-starter-netflix-eureka-client"
build.gradle 参考示例:
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'vip.wuweijie.camel.runtime'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
ext {
camelVersion = '3.2.0'
springCloudVersion = 'Hoxton.SR3'
}
repositories {
mavenLocal()
maven { url "http://maven.aliyun.com/nexus/content/groups/public/" }
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
imports {
mavenBom "org.apache.camel.springboot:camel-spring-boot-dependencies:${camelVersion}"
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation "org.apache.camel.springboot:camel-spring-boot-starter"
implementation "org.apache.camel.springboot:camel-zipkin-starter"
implementation "org.apache.camel.springboot:camel-http-starter"
implementation "org.apache.camel.springboot:camel-netty-http-starter"
implementation "org.apache.camel.springboot:camel-netty-starter"
implementation "org.apache.camel.springboot:camel-ribbon-starter"
implementation "org.apache.camel.springboot:camel-service-starter"
implementation "org.apache.camel.springboot:camel-spring-cloud-starter"
implementation "org.apache.camel.springboot:camel-spring-cloud-netflix-starter"
implementation "org.springframework.cloud:spring-cloud-starter-netflix-eureka-client"
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
相关配置
按照正常配置 Spring Boot Eureka Client 的方式:
eureka:
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://eureka.sia.lo:8761/eureka
spring:
application:
name: simple-micro-service
微服务调用示例
如图,Eureka 中有两个服务:
SIMPLE-MICRO-SERVICE
:提供服务CAMEL-MICRO-SERVICE
:接入微服务的 Camel
其中,SIMPLE-MICRO-SERVICE
有个接口:
@RestController
@RequestMapping("/simple")
public class SimpleController {
@GetMapping("/hello")
public Mono<String> hello() {
return Mono.just("hello, world. --simple-micro-service");
}
}
Camel 路由:
@Component
public class SampleRoute extends RouteBuilder {
@Override
public void configure() throws Exception {
restConfiguration()
.port(8081)
;
from("rest:get:simple:/{path}")
.serviceCall("netty-http:simple-micro-service")
.to("log:SampleRoute?showAll=true")
;
}
}
请求 Camel 的 Rest 接口,结果如下:
GET http://localhost:8081/simple/hello
HTTP/1.1 200 OK
content-length: 36
content-type: text/plain;charset=UTF-8
connection: keep-alive
hello, world. --simple-micro-service
Response code: 200 (OK); Time: 30ms; Content length: 36 bytes
源码解读
相关 Jar:
- camel-api-3.2.0.jar
- camel-spring-cloud-3.2.0.jar
- spring-cloud-netflix-eureka-client-2.2.2.RELEASE.jar
camel-api
包中有个 interface ServiceDiscovery
package org.apache.camel.cloud;
import java.util.List;
/**
* Allows SPIs to implement custom Service Discovery.
*
* @see ServiceChooser
* @see ServiceDefinition
*/
public interface ServiceDiscovery {
/**
* Gets the list of services.
* <p/>
* This method may return an empty list.
*
* @param name the service name
*/
List<ServiceDefinition> getServices(String name);
}
camel-spring-cloud
实现了上面的 interface CamelSpringCloudServiceDiscovery
package org.apache.camel.spring.cloud;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.camel.cloud.ServiceDefinition;
import org.apache.camel.cloud.ServiceDiscovery;
import org.apache.camel.impl.cloud.DefaultServiceDefinition;
import org.springframework.cloud.client.discovery.DiscoveryClient;
public class CamelSpringCloudServiceDiscovery implements ServiceDiscovery {
// 这里使用了 Spring Cloud 的接口 DiscoveryClient
private final DiscoveryClient discoveryClient;
public CamelSpringCloudServiceDiscovery(DiscoveryClient discoveryClient) {
this.discoveryClient = discoveryClient;
}
@Override
public List<ServiceDefinition> getServices(String name) {
return discoveryClient.getInstances(name).stream()
.map(
si -> {
return DefaultServiceDefinition.builder()
.withName(si.getServiceId())
.withHost(si.getHost())
.withPort(si.getPort())
.withId(name)
.withMeta(si.getMetadata())
.build();
}
).collect(Collectors.toList());
}
}
上述代码调用了 DiscoveryClient
接口,这个接口有很多实现类,其中就包括了 spring-cloud-netflix-eureka-client
提供的 EurekaDiscoveryClient
Camel 没有直接提供对 Eureka 的支持,但提供了对 Spring Cloud Discovery 相关支持,所以可以选择 Eureka 作为 Spring Cloud 的服务发现,从而让 Camel 与 Eureka 集成。