使用Spring MVC和Feign Client(使用spring cloud)构建端点和客户端.我认为既然两端都需要有相同的注释 - 并且它们必须非常同步.也许我可以在界面中定义它们并让两端实现它.
测试它我有点惊讶它实际上适用于Spring Web结束.
但我无法找到一种方法为Feign客户端做同样的事情.
我基本上有接口:
@RequestMapping("/somebaseurl")
public interface ServiceInterface {
@RequestMapping(value = "/resource/{identifier}", method = RequestMethod.POST)
public SomeResource getResourceByIdentifier(String identifier);
}
Run Code Online (Sandbox Code Playgroud)
然后是RestController
@RestController
public class ServiceController implements ServiceInterface {
public SomeResource getResourceByIdentifier(@PathVariable("identifier") String identifier) {
// Do some stuff that gets the resource
return new SomeResource();
}
}
Run Code Online (Sandbox Code Playgroud)
最后是Feign客户端
@FeignClient("serviceName")
public interface ServiceClient extends ServiceInterface {
}
Run Code Online (Sandbox Code Playgroud)
Feign客户端似乎没有读取继承的注释.那么还有其他方法可以完成同样的事情吗?我可以将ServiceInterface变成Feign客户端而不直接注释它?
我用Spring Boot创建了一个简单的Feign Client:
@FeignClient("spring-cloud-eureka-client")
public interface GreetingClient {
@RequestMapping("/greeting")
String greeting(@RequestParam String name);
}
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试启动一个应用程序时,我收到一个错误:
java.lang.IllegalStateException: RequestParam.value() was empty on parameter 0
Run Code Online (Sandbox Code Playgroud)
首先,我不明白是什么原因和谷歌搜索,但没有找到答案.几乎不可思议地我发现如果明确地写请求参数名称它是有效的:
@RequestParam("name") String name
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:它是一个错误还是可以配置为不明确写入请求参数名称?
我们正在编写一个 Spring Boot 应用程序,并使用 Cloud Contract WireMock 支持来存根支持服务。我们的测试类注释如下:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@AutoConfigureWireMock(port = 0)
public class Tests...
Run Code Online (Sandbox Code Playgroud)
除了一件事之外,这一切都很好:我们发现 Spring Cloud 似乎不会在测试之间重置 WireMock,特别是删除存根,因此测试没有正确隔离。当然,您可以使用@Before包含 a 的方法自己完成此操作reset(),但我们想知道这是否是故意的。是否有一个我们忽略的选项或必须使用的附加注释?
毕竟,不可能在@BeforeClass方法中定义存根,如果总是执行重置,那么存根就会消失,所以我们想知道什么反对开箱即用?
我为我的应用程序创建了API网关,它将充当其他微服务的前端控制器。在生产设置中,我将Nginx用户用作网关的反向代理
API网关在端口8080上运行
Nginx的配置如下
gateway-api.conf:
server {
listen 80;
server_name api.example.com;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://localhost:30010/;
keepalive_timeout 500s;
}
keepalive_timeout 500s;
access_log /var/log/nginx/api.log;
error_log /var/log/nginx/api_error.log;
}
Run Code Online (Sandbox Code Playgroud)
nginx.conf中的超时设置
proxy_connect_timeout 300;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
Run Code Online (Sandbox Code Playgroud)
Spring Cloud Gateway Gradle文件:
compile('org.springframework.cloud:spring-cloud-starter-gateway')
compile('org.springframework.cloud:spring-cloud-starter-openfeign')
compile("org.springframework.boot:spring-boot-starter-actuator")
compile('org.springframework.boot:spring-boot-starter-security')
springBootVersion=2.0.3.RELEASE
springDMPVersion=1.0.4.RELEASE
springPlatformBomVersion=Cairo-SR2
springCloudVersion=Finchley.RELEASE
Run Code Online (Sandbox Code Playgroud)
网关应用程序:
@SpringBootApplication
@ComponentScan(basePackages = {"com.example"})
@EntityScan(basePackages = {"com.example"})
@EnableFeignClients(basePackages = "com.example")
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args); …Run Code Online (Sandbox Code Playgroud) java nginx spring-cloud nginx-reverse-proxy spring-cloud-gateway
使用Spring Cloud,Eureka和Docker可能会遇到一个有趣的异常现象.我不确定我是否发现了一个问题,或者是否有预期的行为,但这里是要点.
我首先开始在一个命名的docker容器中运行eureka.接下来,我使用ClientDiscoveryEnabled启动docker客户端.docker客户端容器正在使用docker"link"参数来获取eureka容器中的主机名可访问性.yaml文件有一个用于连接属性驱动的Eureka的条目:
defaultZone: http://user:${eureka.password}@${host.name}:8761/eureka/
Run Code Online (Sandbox Code Playgroud)
除非我尝试在容器名称中使用下划线,否则一切都很有效.如果我使用下划线来命名我的容器,则客户端容器无法使用Eureka注册完全解析此名称.如果我删除下划线,一切正常.也许我错过了一些事情,这是预期的,但我没有看到任何提及这个"功能".
我的客户来自Spring-Cloud-Samples feign-eureka项目.以下是场景......
这将工作,客户将注册:
sudo docker run -d -p=8761:8761 --name foobar chrisccoy/microsvcdemoeureka
sudo docker run -d -p=7311:7311 --name democlnt --link foobar:foobar chrisccoy/microsvcdemoclnt java -jar /opt/tst/ms_clnt.jar --host.name=foobar
Run Code Online (Sandbox Code Playgroud)
以下不起作用!Eureka将启动,客户端将启动,但无法注册:
sudo docker run -d -p=8761:8761 --name foo_bar chrisccoy/microsvcdemoeureka
sudo docker run -d -p=7311:7311 --name democlnt --link foo_bar:foo_bar chrisccoy/microsvcdemoclnt java -jar /opt/tst/ms_clnt.jar --host.name=foo_bar
Run Code Online (Sandbox Code Playgroud)
以下是日志条目和后续异常:
2015-02-25 18:51:27.762 ERROR 1 --- [pool-4-thread-1] com.netflix.discovery.DiscoveryClient : Can't get a response from http://user:password@foo_bar:8761/eureka/apps/HELLOCLIENT/172.17.0.11:HelloClient:7311
Can't contact any eureka nodes - possibly a security group issue? …Run Code Online (Sandbox Code Playgroud) 使用Spring Boot构建微服务时,很容易编写广泛且易读的集成测试并模拟远程服务请求MockRestServiceServer.
有没有办法使用类似的方法来执行额外的集成测试ZuulProxy?我想要实现的是能够模拟远程服务器,ZuulProxy这些服务器将转发并验证我ZuulFitler的所有操作符合预期.但是,ZuulProxy是否正在使用RestClientNetflix(它似乎被弃用?),它自然不会使用RestTemplate哪些可以重新配置MockRestServiceServer,我目前无法找到一种很好的方法来模拟远程服务对代理请求的响应.
我有一个微服务,负责处理API会话密钥创建,然后将采取类似于API网关的行为.使用Zuul Proxy对底层公开的服务进行转发,Zuul Filters将检测Session密钥是否有效.因此,集成测试将创建有效会话,然后转发到虚假端点,例如"集成/测试".
通过设置配置属性@WebIntegrationTest,可以指定"集成/测试"是新端点,我可以成功模拟通过RestTemplate但不是Zuul转发处理的所有服务.
实现模拟远期目标服务的最佳方法是什么?
java integration-testing spring-boot spring-cloud netflix-zuul
在过去的两天里,我一直试图找到一个奇怪的重定向问题,但没有成功.
基于spring-cloud示例项目,我已经配置了Eureka,Zuul以及在Zuul后面运行的基本服务.
我有以下方法;
@RequestMapping(method = RequestMethod.POST, value = "/register")
public String registerDevice(Principal principal, String response) {
// ...
return "redirect:/account";
}
Run Code Online (Sandbox Code Playgroud)
表单设置为发布到代理URL,如下所示;
POST https://localhost:8443/service/register
Run Code Online (Sandbox Code Playgroud)
(Zuul在localhost上运行:8443).
本地服务的URL(非代理)将是; HTTP://本地主机:9001 /寄存器
POST调用正确代理到上述方法,但是发送到浏览器的重定向位置是服务的非代理URL; HTTP://本地主机:9001 /帐户
Zuul代理肯定会发送正确的x-forwarded-*头文件,所以我希望Spring中的视图解析器能够根据x-forwarded值构建正确的重定向.
为了证明标头被正确发送,我重新配置了如下方法;
@RequestMapping(method = RequestMethod.POST, value = "/register")
public void registerDevice(Principal, String response, HttpServletResponse response) {
// ...
String rUrl = ServletUriComponentsBuilder.fromCurrentContextPath().path("/account").build().toUriString();
servletResponse.sendRedirect(rUrl);
}
Run Code Online (Sandbox Code Playgroud)
这正确地将浏览器重定向到代理位置; https://开头本地主机:8443 /服务/帐户
这是一个错误,还是预期的行为?我认为使用"redirect:"是为了纪念从代理传递的前向头.
spring-mvc spring-boot spring-cloud netflix-eureka netflix-zuul
我想测试Spring Cloud Vault配置.
我在本地安装了一个Vault服务器,当我尝试write一些键值时它失败并要求我使用vault kv put命令.
虽然此链接中的Spring Cloud Config示例显示了Vault写入命令的用法
这是我得到的错误
$ vault write secret/my-app foo=bar
Error writing data to secret/my-app: Error making API request.
URL: PUT http://127.0.0.1:8200/v1/secret/my-app
Code: 404. Errors:
WARNING! The following warnings were returned from Vault:
* Invalid path for a versioned K/V secrets engine. See the API docs for the
appropriate API endpoints to use. If using the Vault CLI, use 'vault kv put'
for this operation.
Run Code Online (Sandbox Code Playgroud) spring spring-cloud hashicorp-vault spring-cloud-vault-config
在下面的示例中,我将max和core pool size设置为1.但是没有消息正在处理中.当我启用调试日志时,我能够看到从SQS中提取的消息,但我猜它没有被处理/删除.但是,当我将核心和最大池大小增加到2时,似乎会处理消息.
编辑
我相信Spring可能为接收器分配一个线程,该接收器从队列中读取数据,因此无法将线程分配给正在处理消息的侦听器.当我将corepoolsize增加到2时,我看到消息正在从队列中读取.当我添加另一个监听器(用于死信队列)时,我遇到了同样的问题 - 由于没有处理消息,因此2个线程是不够的.当我将corepoolsize增加到3时,它开始处理消息.我假设在这种情况下,分配了1个线程来读取队列中的消息,并为2个侦听器分配了1个线程.
@Configuration
public class SqsListenerConfiguration {
@Bean
@ConfigurationProperties(prefix = "aws.configuration")
public ClientConfiguration clientConfiguration() {
return new ClientConfiguration();
}
@Bean
@Primary
public AWSCredentialsProvider awsCredentialsProvider() {
ProfileCredentialsProvider credentialsProvider = new ProfileCredentialsProvider("credential");
try {
credentialsProvider.getCredentials();
System.out.println(credentialsProvider.getCredentials().getAWSAccessKeyId());
System.out.println(credentialsProvider.getCredentials().getAWSSecretKey());
} catch (Exception e) {
throw new AmazonClientException(
"Cannot load the credentials from the credential profiles file. " +
"Please make sure that your credentials file is at the correct " +
"location (~/.aws/credentials), and is in valid format.",
e); …Run Code Online (Sandbox Code Playgroud) 我的目标是world-service从config-service.
架构:
config-service依赖spring-cloud-config-server于localhost:8888world-service依赖于spring-web和spring-cloud-starter-config。我做了什么:
http://localhost:8888/hello-service/master配置服务器hello-service.properties从config-repo 存储库中获取。(如果你需要它config-service的源代码,我会把它推送到这个仓库。)我的预期结果:world-service使用端口 8081。
我的实际结果:world-service使用端口 8080。
bootstrap.properties
spring.application.name=world-service
spring.cloud.config.uri=http://localhost:8888
Run Code Online (Sandbox Code Playgroud)
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>2.4.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>world-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>world-service</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<spring-cloud.version>2020.0.0-M5</spring-cloud.version>
</properties>
<dependencies>
<dependency> …Run Code Online (Sandbox Code Playgroud) spring-cloud ×10
java ×5
spring ×5
spring-boot ×4
netflix-zuul ×2
amazon-sqs ×1
docker ×1
nginx ×1
spring-mvc ×1
wiremock ×1