为了解决某些问题,一些框架和库应运而生,例如Spring Cloud和Swagger等。这些工具提供了更安全、更一致和更易于使用的API开发方式,使得服务提供者和消费者能够更加高效地协作。
Java传统服务提供和消费直接使用 Rest 存在一些缺陷,其中包括:
缺乏类型安全:
Restful API通常使用JSON或XML等格式来序列化数据,这些格式是文本格式,不包含类型信息。这使得在编写服务提供者和消费者时 -容易犯类型错误- ,从而导致运行时错误。
缺乏编解码器:
Restful API通常需要使用HTTP协议来通信,而HTTP协议是无状态协议,这意味着它不保留任何关于请求或响应的状态信息。因此,服务提供者和消费者需要使用 -编解码器- 来序列化和反序列化请求和响应,这增加了开发的复杂性。
缺乏安全性:
Restful API通常使用HTTP协议进行通信,而HTTP协议是明文协议,不提供任何安全性保障。因此,服务提供者和消费者需要自己实现安全性措施,例如使用OAuth或JWT等 -身份验证机制- 来保护API。
缺乏一致性:
由于Restful API -没有规定数据结构-,因此不同的服务提供者可能使用不同的数据格式和API端点,这使得服务消费者很难与多个服务提供者进行交互。此外,如果服务提供者改变了API端点或数据格式,消费者需要相应地修改代码,这增加了开发和维护的复杂性。
回顾传统项目
普通服务提供者 - api-provide
普通服务消费者 - api-consumer
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kF8g0cMM-1687704560577)(img/image-20230625050357083.png)]
模拟具备各种API功能的项目 【maven】
这是个简单项目,接口未使用 身份验证机制、规定数据结构等
<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.0modelVersion> <parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>2.7.12version> <relativePath/> parent> <groupId>com.devgroupId> <artifactId>api-provideartifactId> <version>0.0.1-SNAPSHOTversion> <name>api-providename> <description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
启动类
package com.dev.apiprovide;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProvideApplication {
public static void main(String[] args) {
SpringApplication.run(ProvideApplication.class, args);
}
}
package com.dev.apiprovide.ctrl;
import java.util.HashMap; import java.util.Map; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController;
@RestController()
@RequestMapping("test")
public class TestCtrl{
@RequestMapping(value = "api", method = RequestMethod.GET)
public Map<String, Object> api(String data){
Map<String, Object> resMap = new HashMap<>();
if(ObjectUtils.isEmpty(data)){
resMap.put("code", 500);
resMap.put("msg", "is null");
} else {
resMap.put("code", 200);
resMap.put("msg", "success");
}
return resMap;
}
}
server.port= 18081
模拟具使用API功能的项目 【maven】
这是个简单项目,使用http客户端直接调用访问。
<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.0modelVersion> <parent> <groupId>org.springframework.bootgroupId> <artifactId>spring-boot-starter-parentartifactId> <version>2.7.12version> <relativePath/> parent> <groupId>com.devgroupId> <artifactId>api-consumerartifactId> <version>0.0.1-SNAPSHOTversion> <name>api-consumername> <description>Demo project for Spring Bootdescription>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.apache.httpcomponentsgroupId>
<artifactId>httpclientartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
启动类
package com.dev.apiconsumer;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
rest 工具配置
package com.dev.apiconsumer.cfg;
import org.apache.http.client.HttpClient; import org.apache.http.conn.HttpClientConnectionManager; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
/**
* http连接管理器
* @return
*/
@Bean("cdac_rtc_pgcm")
public HttpClientConnectionManager poolingHttpClientConnectionManager() {
/*// 注册http和https请求
Registry registry = RegistryBuilder.create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);*/
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
// 最大连接数
poolingHttpClientConnectionManager.setMaxTotal(500);
// 同路由并发数(每个主机的并发)
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);
return poolingHttpClientConnectionManager;
}
/**
* HttpClient
* @param poolingHttpClientConnectionManager
* @return
*/
@Bean("cdac_rtc_hc")
public HttpClient httpClient(@Autowired @Qualifier("cdac_rtc_pgcm")HttpClientConnectionManager poolingHttpClientConnectionManager) {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// 设置http连接管理器
httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
/*// 设置重试次数
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));*/
// 设置默认请求头
/*List headers = new ArrayList<>();
headers.add(new BasicHeader("Connection", "Keep-Alive"));
httpClientBuilder.setDefaultHeaders(headers);*/
return httpClientBuilder.build();
}
/**
* 请求连接池配置
* @param httpClient
* @return
*/
@Bean("cdac_rtc_chq")
public ClientHttpRequestFactory clientHttpRequestFactory(@Autowired @Qualifier("cdac_rtc_hc") HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
// httpClient创建器
clientHttpRequestFactory.setHttpClient(httpClient);
// 连接超时时间/毫秒(连接上服务器(握手成功)的时间,超出抛出connect timeout)
clientHttpRequestFactory.setConnectTimeout(5 * 1000);
// 数据读取超时时间(socketTimeout)/毫秒(务器返回数据(response)的时间,超过抛出read timeout)
clientHttpRequestFactory.setReadTimeout(10 * 1000);
// 连接池获取请求连接的超时时间,不宜过长,必须设置/毫秒(超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool)
clientHttpRequestFactory.setConnectionRequestTimeout(10 * 1000);
return clientHttpRequestFactory;
}
/**
* rest模板
* @return
*/
@Bean
public RestTemplate restTemplate(@Autowired @Qualifier("cdac_rtc_chq")ClientHttpRequestFactory clientHttpRequestFactory) {
// boot中可使用RestTemplateBuilder.build创建
RestTemplate restTemplate = new RestTemplate();
// 配置请求工厂
restTemplate.setRequestFactory(clientHttpRequestFactory);
return restTemplate;
}
}
调用提供放接口的api
package com.dev.apiconsumer.ctrl;
import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("test")
public class TestRCtrl {
@Autowired
private RestTemplate restTemplate;
// 提供者的IP:端口
private String hostsUrl = "http://192.168.79.71:18081";
@RequestMapping(value = "api", method = RequestMethod.GET)
public Object api(String data){
return restTemplate.getForObject(hostsUrl + "/test/api?data=null", HashMap.class, data);
}
}
server.port= 18082
Spring Cloud是基于Spring Boot的实现,它提供了一系列的工具和组件,用于构建分布式系统。
Spring Boot是Spring Cloud的基础,它提供了一系列的工具和组件,用于构建独立的、可部署的微服务。
Spring Cloud提供了许多组件,例如服务注册中心、服务发现、负载均衡、断路器等,学习这些组件的使用和配置是非常重要的。
通过实战来加深对Spring Cloud的理解,例如实现一个简单的微服务、使用Spring Cloud实现服务注册和发现、使用Spring Cloud实现负载均衡等。
Spring Cloud是一个不断发展的技术,需要不断学习和实践,以跟上它的步伐。参加技术交流会议、阅读官方文档和书籍、关注技术社区都是不错的学习途径。
首先需要了解Spring Cloud的基本概念和架构。这可以通过阅读官方文档和在线教程来学习。
同时需掌握Spring Boot的基础知识,这是Spring Cloud的基础。可以通过学习Spring Boot的官方文档和在线教程来了解Spring Boot的基本概念、特性和使用方法。
然后,你需要学习Spring Cloud的组件,例如服务注册中心、服务发现、负载均衡、断路器等。可以通过阅读官方文档、书籍和在线教程来学习这些组件的使用和配置方法。
在掌握Spring Cloud的基本概念、Spring Boot和Spring Cloud的组件后,你可以开始练习实战。例如,可以尝试实现一个简单的微服务、使用Spring Cloud实现服务注册和发现、使用Spring Cloud实现负载均衡等。通过实战来加深对Spring Cloud的理解和使用。
最后,需要持续学习和实践。参加技术交流会议、阅读官方文档和书籍、关注技术社区都是不错的学习途径。同时,需要保持耐心和坚持不懈的学习态度,遇到问题时可以寻求帮助他人或寻求社区的支持。
是基于Spring Framework的一套全栈解决方案,用于构建分布式系统中的微服务架构。
Spring Cloud提供了丰富的组件和工具,可以快速地构建复杂的分布式系统。
它主要包括以下组件:
Eureka:提供 服务发现和注册 的功能,可以让微服务之间相互通信。
Ribbon:提供 客户端负载均衡 的功能,可以将请求分发到多个服务实例中去。
Feign:提供 声明式的HTTP 客户端,可以让调用远程服务的代码更加简洁。
Hystrix:提供 熔断器 的功能,可以保证系统在出现故障时也能够正常运行。
Zuul:提供 网关 的功能,可以将请求路由到不同的微服务实例中。
Spring Cloud的架构是由多个微服务组成的分布式系统。每个微服务都是一个独立的单元,可以独立进行开发、部署和管理。这些微服务通过Spring Cloud提供的各种组件和工具相互协作,最终形成一个完整的应用程序。
在这种架构下,每个微服务都有自己的数据存储和处理能力,可以独立进行水平扩展。通过服务注册与发现,微服务可以相互发现和调用,从而形成一个强大的分布式系统。
总之,Spring Cloud是一套全栈的微服务解决方案,它提供了丰富的组件和工具,可以帮助开发人员快速构建分布式系统。
复杂性:
Spring Cloud 是一个庞杂的框架,使用它需要具备一定的技术能力。对于一些中小型企业来说,他们可能没有足够的技术资源来使用这个框架。
学习成本:
由于 Spring Cloud 是一个庞杂的框架,学习它需要花费很长时间。中小型企业可能没有足够的时间和资源来培训他们的团队。
部署复杂性:
将 Spring Cloud 部署到生产环境中需要额外的努力和复杂性。中小型企业可能没有足够的资源来应对这个挑战。
依赖性:
Spring Cloud 依赖其他的 Spring 框架,如果应用程序不是基于 Spring 架构构建的,那么将它转换为 Spring Cloud 可能具有很高的成本和风险。
对于中小型企业来说,他们可能没有人力、时间和资源来应对这些缺点。
如果他们有足够的技术团队和时间做好调研和培训,那么使用 Spring Cloud 可以让他们更好地应对微服务架构。
微服务过多,治理成本高:
当系统中的微服务数量过多时,治理成本会变高,这会导致维护和管理的困难。
分布式系统开发的成本高:
分布式系统的开发需要考虑的问题比较多,例如容错、分布式事务等,这会导致开发的成本变高。
重复工作:
在某些情况下,由于微服务的拆分可能会导致重复的工作,这会影响开发效率和系统性能。
复杂度增加:
由于微服务的数量增加和分布式的特性,系统的复杂度会随之增加,这会导致调试和排查问题的难度增加。
安全性考虑:
在分布式系统中,需要考虑安全性问题,例如数据泄露、服务注入等,这需要投入更多的时间和精力来确保系统的安全性。
因此,在选择使用Spring Cloud时,需要根据具体的项目场景和需求来评估其优缺点,并制定合适的解决方案
初步了解 Eureka 服务注册发现
定义父工程,规范后面的项目模块依赖版本
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.devgroupId>
<artifactId>cloud-parentartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<name>spring cloud eureka 学习 name>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.12version>
<relativePath/>
parent>
<properties>
<spring-cloud.version>2021.0.7spring-cloud.version>
properties>
<modules>
<module>eureka-servermodule>
<module>eureka-client-providemodule>
modules>
project>
注意
当在存在权限的目录下运行可能导致以下消息出现
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.202-b08 mixed mode):
"RMI TCP Accept-0" #15 daemon prio=5 os_prio=0 tid=0x00007f67fc6ae000 nid=0x4bfd runnable [0x00007f67d7540000]
java.lang.Thread.State: RUNNABLE
at java.net.PlainSocketImpl.socketAccept(Native Method)
at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at sun.management.jmxremote.LocalRMIServerSocketFactory$1.accept(LocalRMIServerSocketFactory.java:52)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.executeAcceptLoop(TCPTransport.java:405)
at sun.rmi.transport.tcp.TCPTransport$AcceptLoop.run(TCPTransport.java:377)
at java.lang.Thread.run(Thread.java:748)
这是 Eureka 服务端 项目
<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.0modelVersion>
<parent>
<groupId>com.devgroupId>
<artifactId>cloud-parentartifactId>
<version>1.0-SNAPSHOTversion>
parent>
<artifactId>eureka-serverartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>服务端-eureka-servername>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
server.port= 18090
spring:
freemarker:
template-loader-path: classpath:/templates/
prefer-file-system-access: false
eureka:
instance:
# 本机ip
hostname: 127.0.0.1
client:
# 在 Eureka 注册
registerWithEureka: false
# 获取注册表
fetchRegistry: false
serviceUrl:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
package com.dev.eurekaserv;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
中文汉化自行百度
http://192.168.79.71:18090
sudo firewall-cmd --add-port=18090/tcp --permanent
sudo systemctl restart firewalld.service
这是 Eureka 客户端 项目,参与服务提供
<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.0modelVersion>
<parent>
<groupId>com.devgroupId>
<artifactId>cloud-parentartifactId>
<version>1.0-SNAPSHOTversion>
parent>
<artifactId>eureka-serverartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>服务端-eureka-servername>
<properties>
<java.version>1.8java.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
server.port= 18091
spring:
application:
name: api-eureka-provide
# https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/#service-discovery-eureka-clients
eureka:
client:
serviceUrl:
defaultZone: http://192.168.79.71:18090/eureka/
rest-template-timeout:
connect-timeout: 5000
connect-request-timeout: 8000
socket-timeout: 10000
package com.dev.eurekaclientprovide;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class EurekaClientProvideApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientProvideApplication.class, args);
}
}
package com.dev.eurekaclientprovide.ctrl;
import java.util.HashMap;
import java.util.Map;
import org.springframework.http.MediaType;
import org.springframework.util.ObjectUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController()
public class TestCtrl{
@RequestMapping(value = "test/def", method = RequestMethod.GET)
public Map<String, Object> def(String data){
Map<String, Object> resMap = new HashMap<>();
if(ObjectUtils.isEmpty(data)){
resMap.put("code", 500);
resMap.put("msg", "is null");
} else {
resMap.put("code", 200);
resMap.put("msg", "success");
resMap.put("data", data);
}
return resMap;
}
@RequestMapping(value = "test/json", method = RequestMethod.GET, produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE)
public Map<String, Object> json(String data){
Map<String, Object> resMap = new HashMap<>();
if(ObjectUtils.isEmpty(data)){
resMap.put("code", 500);
resMap.put("msg", "is null");
} else {
resMap.put("code", 200);
resMap.put("msg", "success");
resMap.put("data", data);
}
return resMap;
}
}
http://192.168.79.71:18091/test/def
http://192.168.79.71:18091/test/json
sudo firewall-cmd --add-port=18091/tcp --permanent && sudo systemctl restart firewalld.service
<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 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.devgroupId>
<artifactId>cloud-parentartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<name>spring cloud eureka 学习 name>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.7.12version>
<relativePath/>
parent>
<properties>
<spring-cloud.version>2021.0.7spring-cloud.version>
properties>
<modules>
<module>eureka-servermodule>
<module>eureka-client-providemodule>
<module>eureka-client-p-ribbonmodule>
modules>
project>
一个对外项目,简单演示如何进入注册中心消费
当有人找自己,但自己没有服务,就问服务中心有没有符合条件的代为帮忙
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<parent>
<groupId>com.devgroupId>
<artifactId>cloud-parentartifactId>
<version>1.0-SNAPSHOTversion>
parent>
<artifactId>eureka-client-c-ribbonartifactId>
<version>0.0.1-SNAPSHOTversion>
<packaging>jarpackaging>
<name>客户端-Eureka-p-ribbon 消费name>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<start-class>com.dev.Appstart-class>
<java.version>1.8java.version>
<lombok.version>1.14.8lombok.version>
<log4jdbc.log4j2.version>1.16log4jdbc.log4j2.version>
<rest.assured.version>2.3.3rest.assured.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
<scope>providedscope>
dependency>
<dependency>
<groupId>org.bgee.log4jdbc-log4j2groupId>
<artifactId>log4jdbc-log4j2-jdbc4.1artifactId>
<version>${log4jdbc.log4j2.version}version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.jayway.restassuredgroupId>
<artifactId>rest-assuredartifactId>
<version>${rest.assured.version}version>
<scope>testscope>
dependency>
dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
plugin>
plugins>
build>
project>
server.port= 18092
# 设置最大内存
spring.datasource.tomcat.max-active= 300
# 设置最小内存
spring.datasource.tomcat.min-idle= 128
s.eureka.host= 192.168.79.71
s.eureka.port= 18090
s.provide.name= api-eureka-provide
spring:
application:
name: eureka-client-c-ribbon
# https://docs.spring.io/spring-cloud-netflix/docs/current/reference/html/#service-discovery-eureka-clients
eureka:
client:
serviceUrl:
defaultZone: http://${s.eureka.host}:${s.eureka.port}/eureka/
rest-template-timeout:
connect-timeout: 5000
connect-request-timeout: 8000
socket-timeout: 10000
package com.dev.eurekaclientcribbon;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class EurekaClientCRibbonApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientCRibbon.class, args);
}
}
package com.dev.eurekaclientcribbon.ctrl;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController()
@PropertySource("classpath:application.properties")
public class TestCtrl{
@Autowired
RestTemplate restTemplate;
// 提供者
@Value("${s.provide.name}")
private String hostsUrl;
@RequestMapping(value = "test/def", method = RequestMethod.GET)
public Object def(String data){
return restTemplate.getForObject("http://" +hostsUrl + "/test/def?data={data}", HashMap.class, data);
}
@RequestMapping(value = "test/json", method = RequestMethod.GET, produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE)
public Object json(String data){
return restTemplate.getForObject("http://" +hostsUrl + "/test/json?data={data}", HashMap.class, data);
}
}
package com.dev.eurekaclientcribbon.cfg;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
/**
* http连接管理器
* @return
*/
@Bean("cdac_rtc_pgcm")
public HttpClientConnectionManager poolingHttpClientConnectionManager() {
/*// 注册http和https请求
Registry registry = RegistryBuilder.create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(registry);*/
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager();
// 最大连接数
poolingHttpClientConnectionManager.setMaxTotal(500);
// 同路由并发数(每个主机的并发)
poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100);
return poolingHttpClientConnectionManager;
}
/**
* HttpClient
* @param poolingHttpClientConnectionManager
* @return
*/
@Bean("cdac_rtc_hc")
public HttpClient httpClient(@Autowired @Qualifier("cdac_rtc_pgcm")HttpClientConnectionManager poolingHttpClientConnectionManager) {
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// 设置http连接管理器
httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
/*// 设置重试次数
httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true));*/
// 设置默认请求头
/*List headers = new ArrayList<>();
headers.add(new BasicHeader("Connection", "Keep-Alive"));
httpClientBuilder.setDefaultHeaders(headers);*/
return httpClientBuilder.build();
}
/**
* 请求连接池配置
* @param httpClient
* @return
*/
@Bean("cdac_rtc_chq")
public ClientHttpRequestFactory clientHttpRequestFactory(@Autowired @Qualifier("cdac_rtc_hc") HttpClient httpClient) {
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
// httpClient创建器
clientHttpRequestFactory.setHttpClient(httpClient);
// 连接超时时间/毫秒(连接上服务器(握手成功)的时间,超出抛出connect timeout)
clientHttpRequestFactory.setConnectTimeout(5 * 1000);
// 数据读取超时时间(socketTimeout)/毫秒(务器返回数据(response)的时间,超过抛出read timeout)
clientHttpRequestFactory.setReadTimeout(10 * 1000);
// 连接池获取请求连接的超时时间,不宜过长,必须设置/毫秒(超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool)
clientHttpRequestFactory.setConnectionRequestTimeout(10 * 1000);
return clientHttpRequestFactory;
}
/**
* rest模板
* @return
*/
@Bean("restTemplate")
@Primary
@LoadBalanced
public RestTemplate restTemplate(@Autowired @Qualifier("cdac_rtc_chq")ClientHttpRequestFactory clientHttpRequestFactory) {
// boot中可使用RestTemplateBuilder.build创建
RestTemplate restTemplate = new RestTemplate();
// 配置请求工厂
restTemplate.setRequestFactory(clientHttpRequestFactory);
return restTemplate;
}
}
http://192.168.79.71:18092/test/def
http://192.168.79.71:18092/test/json
sudo firewall-cmd --add-port=18092/tcp --permanent && sudo systemctl restart firewalld.service