# 一.基础配置

# 1.指定文件启动

#Program arguments中配置环境信息
--spring.profiles.active=eureka8767
1
2

# 2.返回 json 格式

 @GetMapping(value = "{id}", produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE)
1

# 3.如何复制模块?

1.先拷贝一份代码

2.修改项目名称

3.修改pom
<artifactId>springcloud-service-goods-9300</artifactId>
<name>springcloud-service-goods-9300</name>

4.修改application.yaml

5.修改GoodsApplication9300

6.删除iml

7.刷新maven
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 4.配置唯一实例

#服务提供者
eureka:
  client:
    service-url:
      defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/
  instance:
    lease-renewal-interval-in-seconds: 2 #每间隔2s,向服务端发送一次心跳,证明自己依然"存活”
    lease-expiration-duration-in-seconds: 10 #告诉服务端,如果我10s之内没有给你发心跳,就代表我故障了,将我踢出掉
    prefer-ip-address: true #告诉服务端,服务实例以IP作为链接,而不是取机器名
    instance-id: springcloud-service-goods-9300 #告诉服务端,服务实例的id,id要是唯一的
1
2
3
4
5
6
7
8
9
10

# 5.端点监控

#错误的配置
management:
  endpoints:
    web:
      exposure:
        include: *

#正确的配置
management:
  endpoints:
    web:
      exposure:
        include: '*'
1
2
3
4
5
6
7
8
9
10
11
12
13

# 二.eureka

# 1.门户接口

@RestController
@RequestMapping("portal")
public class PortalController {
    /**
     * http直接访问
     */
    private static final String GOODS_URL = "http://localhost:9100/kwanGoodsInfo/";
    /**
     * eureka访问
     */
    private static final String GOODS_URL_2 = "http://goods-service/kwanGoodsInfo/";
    /**
     * 服务对象
     */
    @Autowired
    private RestTemplate restTemplate;
    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @GetMapping(value = "{id}", produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE)
    public Result selectOne(@PathVariable Serializable id) {
        //调用远程的controller
        ResponseEntity<Result> forEntity = restTemplate.getForEntity(GOODS_URL_2 + id, Result.class);
        return Result.ok(forEntity);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

# 2.配置文件

#端口号
server:
  port: 8766

spring:
  application:
    name: eurka-server

eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false #由于该应用为注册中心,所以设置 为 false, 代表不向注册中心注册自己。
    fetch-registry: false #由于注册中心的职责就是维护服务实例, 它并不需要去检索服务, 所以也设置为 false。
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 3.高可用配置

#端口号
server:
  port: 8767

spring:
  application:
    name: eurka-server

eureka:
  instance:
    hostname: eureka8767
  client:
    register-with-eureka: false #由于该应用为注册中心,所以设置 为 false, 代表不向注册中心注册自己。
    fetch-registry: false #由于注册中心的职责就是维护服务实例, 它并不需要去检索服务, 所以也设置为 false。
    serviceUrl:
      defaultZone: http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 4.启动类

@EnableEurekaServer
@SpringBootApplication
public class Application {
	public static void main(String[] args) {
		new SpringApplicationBuilder(Application.class).web(true).run(args);
	}
}
1
2
3
4
5
6
7

# 三.feign

# 1.pom 文件

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-feign</artifactId>
	<version>1.4.7.RELEASE</version>
</dependency>
1
2
3
4
5

# 2.api 接口

@FeignClient("goods-service/kwanGoodsInfo")
public interface ComputeClient {

  @RequestMapping(method = RequestMethod.GET, value = "{id}", produces = 	MediaType.APPLICATION_PROBLEM_JSON_VALUE)
  Result selectOne(@PathVariable Serializable id);

}
1
2
3
4
5
6
7

# 3.门户请求

@RestController
@RequestMapping("feign")
public class FeignController {
    @Autowired
    private ComputeClient computeClient;
    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @GetMapping(value = "{id}", produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE)
    public Result selectOne(@PathVariable Serializable id) {
        //调用远程的controller
        return computeClient.selectOne(id);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 4.配置文件

#端口号
server:
  port: 8081

spring:
  application:
    name: feign-service #服务名称

#服务提供者
eureka:
  client:
    service-url:
      defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/

feign:
  hystrix:
    enabled: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 四.ribbon

# 1.LoadBalanced

@Configuration
public class RestConfig {

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
1
2
3
4
5
6
7
8
9

# 2.负载均衡配置

@Configuration
public class RestConfig {

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    /**
     * 自定义负载均衡
     */
    @Bean
    public IRule microIrule() {
        return new RandomRule();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 3.自定义负载均衡

public class MicroServiceLoadBalanceRule extends AbstractLoadBalancerRule {

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }

    @Override
    public Server choose(Object key) {

        ILoadBalancer lb = getLoadBalancer();
        if (lb == null) {
            return null;
        }

        List<Server> servers = lb.getReachableServers();
        if (servers.isEmpty()){
            return null;
        }

        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        String uri = request.getRequestURI();
        boolean specialApi = uri.startsWith("/api") ;
        // /api路径优先转发到指定的机器
        if(specialApi){
            String ip = "192.168.2.3";
            Server chooseServer = null;
            for (Server server : servers) {
                if (server.getHost().equals(ip)) {
                    chooseServer = server;
                }
            }
            if(chooseServer == null){
                chooseServer = servers.stream().findFirst().orElse(null);
            }
            return chooseServer;
        }
        return servers.get(new Random().nextInt(servers.size()));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 4.配置文件

application.yaml 配置文件:

micro-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.mk.springcloud.gateway.loadbalance.MicroServiceLoadBalanceRule
1
2
3
#开饥饿加载,默认是懒加载,启动后就从注册中心获取服务进行缓存
ribbon.eager-load.enabled=true

#为哪些客户端开启饥饿加载,多个客户端使用逗号分隔(非必须)
ribbon.eager-load.clients=29-nacos-discovery-consumer

#读取时间
feign.client.config.default.read-timeout=1

#连接时间
feign.client.config.default.connect-timeout=1

#针对具体应用设置超时时间
feign.client.config.29-nacos-discovery-provider.read-timeout=1

#就是允许定义相同的bean对象 去覆盖原有的,默认是false
spring.main.allow-bean-definition-overriding=true

#开启feign对httpClient的支持
feign.httpclient.enabled=true

#最大连接数
feign.httpclient.max-connections=200

#每个路径的最大连接数
feign.httpclient.max-connections-per-route=50

#配置规则
ribbon:
  NFLoadBalancerClassName: #ILoadBalancer 该接口实现类
  NFLoadBalancerRuleClassName: #IRule 该接口实现类
  NFLoadBalancerPingClassName: #Iping 该接口实现类
  NIWSServerListClassName: #ServerList 该接口实现类
  NIWSServerListFilterClassName: #ServiceListFilter 该接口实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

# 5.自定 rule

public class MicroRibbonConfig {
    @Bean
    public IRule microIRule(){
        return new MicroServiceLoadBalanceRule();
    }
}
1
2
3
4
5
6
@RibbonClient(name = "micro-service", configuration = MicroRibbonConfig.class)
public class RibbonClientConfig {
}
1
2
3

# 五.Hystrix

# 1.Ribbon 中引入 Hystrix

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
1
2
3
4
@EnableFeignClients
@EnableHystrix
@EnableEurekaClient
@SpringBootApplication
public class RibbonApplication {
	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
	public static void main(String[] args) {
		SpringApplication.run(RibbonApplication.class, args);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Service
public class ComputeService {

    @Autowired
    RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "addServiceFallback")
    public String addService() {
        return restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody();
    }

    public String addServiceFallback() {
        return "error";
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
public class ConsumerController {

    @Autowired
    private ComputeService computeService;

    @RequestMapping(value = "/add", method = RequestMethod.GET)
    public String add() {
        return computeService.addService();
    }

}
1
2
3
4
5
6
7
8
9
10
11
12

# 2.Feign 使用 Hystrix

@FeignClient(value = "compute-service", fallback = ComputeClientHystrix.class)
public interface ComputeClient {

    @RequestMapping(method = RequestMethod.GET, value = "/add")
    Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b);
}
1
2
3
4
5
6
@Component
public class ComputeClientHystrix implements ComputeClient {

    @Override
    public Integer add(@RequestParam(value = "a") Integer a, @RequestParam(value = "b") Integer b) {
        return -9999;
    }

}
1
2
3
4
5
6
7
8
9
#开启feign开始hystrix的支持
feign:
  hystrix:
    enabled: true

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000 #hystrix超时时间
        timeout:
          enabled: true #开启hystrix超时管理
ribbon:
  ReadTimeout: 2000 #请求超时时间
  http:
    client:
      enabled: true #开启ribbon超时管理
  ConnectTimeout: 2000 #连接超时时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

注解方式设置超时时间

    @HystrixCommand(fallbackMethod = "addServiceFallback", commandProperties = {
            @HystrixProperty(name = "execution.timeout.enabled", value = "true"),
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "6000")
    })
1
2
3
4

# 3.Hystrix Dashboard

<!--spring-cloud-starter-netflix-hystrix -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<!--springboot开发自动热部署-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-devtools</artifactId>
  <optional>true</optional>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@EnableHystrixDashboard
@SpringBootApplication
public class HystrixDashboardApplication {

    public static void main(String[] args) {

        SpringApplication.run(HystrixDashboardApplication.class, args);
    }
}
1
2
3
4
5
6
7
8
9
#端口号
server:
  port: 9909

spring:
  application:
    name: hystrix-dashboard-service #服务名称
1
2
3
4
5
6
7
#访问链接
http://localhost:9909/hystrix
1
2

# 4.超时配置

如果ribbon和hystrix同时开启,则以配置最小的为准。

#开启ribbon超时管理
ribbon.http.client.enabled=true
#请求超时时间
ribbon.ReadTimeout=2000
#连接超时时间
ribbon.ConnectTimeout=2000
#开启hystrix超时管理
hystrix.command.default.execution.timeout.enabled=true
#hystrix超时时间
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
1
2
3
4
5
6
7
8
9
10

# 六.config

# 1.pom 依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
1
2
3
4

# 2.config 配置

#端口号
server:
  port: 7001

spring:
  application:
    name: config-service #服务名称
  cloud:
    config:
      server:
        git:
          uri: https://gitcode.net/qyj19920704/springcloud-config.git
          search-paths:
            - config-repo
          username: 13113691357
          password: 15671628341qwe
      label: master
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 3.启动类

@EnableConfigServer
@SpringBootApplication
public class ConfigApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigApplication.class, args);
    }
}
1
2
3
4
5
6
7

# 4.隐射关系

URL 与配置文件的映射关系如下:

  • /{application}/{profile}[/{label}]
  • /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

上面的 url 会映射{application}-{profile}.properties对应的配置文件,{label}对应 git 上不同的分支,默认为 master。

#访问下面链接,可以看到git中的配置信息
http://localhost:7001/didispace/prod/config-label-test
1
2

# 5.应用服务配置

bootstrap.properties,不需要 application.yaml

spring.application.name=didispace
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.uri=http://localhost:7001/
server.port=7002
1
2
3
4
5

# 6.应用服务门户

@RefreshScope
@RestController
class ConfigController {

    @Value("${from}")
    private String from;

    @RequestMapping("/from")
    public String from() {
        return this.from;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 七.zuul

# 1.pom 依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
1
2
3
4
5
6
7
8

# 2.配置文件

网关配置方式有多种,默认、URL、服务名称、排除|忽略、前缀

#端口号
server:
  port: 8888
spring:
  application:
    name: zuul-service #服务名称
#路由规则:
zuul:
  sensitiveHeaders: Cookie,Set-Cookie,Authorization
  routes:
    portal:
      path: /portal-service/** #访问路径:http:/localhost:8888/portal-service/portal/1
      service-id: portal-service
    goods:
      path: /goods-service/** #http:/localhost:8888/goods-service/kwanGoodsInfo/1
      service-id: goods-service
  host:
    connect-timeout-millis: 5000 #超时时间
  prefix: /api #访问路径:http:/localhost:8888/api/portal-service/portal/1    http:/localhost:8888/api/goods-service/kwanGoodsInfo/1
  retryable: true
  ignored-services: portal-service #感略某个服务名,禁止通过该服务名访可
  #  ignored-services: *  #禁止通过所有的服务名访间
  ignored-patterns: /**/feign/** #不给匹配此棋式的路径进行路由·那么你到时候访间不到
  LogFilter:
    route:
      disable: true #用LogFilter过滤器
  #  semaphore:
  #    max-semaphores: 100
  #  ribbon-isolation-strategy: thread
  #  strip-prefix: false
#服务提供者
eureka:
  client:
    service-url:
      defaultZone: http://eureka8767:8767/eureka/,http://eureka8768:8768/eureka/,http://eureka8769:8769/eureka/
ribbon:
  ConnectTimeout: 250 #连接超时时间(ms),默认值为250ms
  ReadTimeout: 2000 #通信超时时间(ms),默认值为2000ms
  MaxAutoRetriesNextServer: 0 #对同一服务不同实例重试次数(同一服务下集群个数的重试次数)
  MaxAutoRetries: 2 #对同一实例重试的次数(单个集群节点服务重试的次数)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

# 3.启动类

@EnableZuulProxy
@SpringBootApplication
public class ZuulApplication {

    public static void main(String[] args) {

        SpringApplication.run(ZuulApplication.class, args);
    }

}
1
2
3
4
5
6
7
8
9
10

# 4.访问地址

#通过zuul访问服务的,URL地址默认格式为:
http://zuulHostIp:port/要访问的服务名称/服务中的URL
1
2

# 八.consul

# 1.安装

#安装地址
https://developer.hashicorp.com/consul/downloads

#执行
brew tap hashicorp/tap
brew install hashicorp/tap/consul

#启动
consul agent -dev
1
2
3
4
5
6
7
8
9

image-20230111175257809

# 2.控制台

#访问地址
http://127.0.0.1:8500/ui/dc1/services
1
2

image-20230111175332896

# 3.配置信息

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
1
2
3
4
#端口号
server:
  port: 8500

spring:
  application:
    name: consul-service #服务名称
  cloud:
    consul:
      host: localhost
      port: 8500
1
2
3
4
5
6
7
8
9
10
11
@SpringBootApplication
public class ConsulApplication {

    public static void main(String[] args) {

        SpringApplication.run(ConsulApplication.class, args);
    }

}
1
2
3
4
5
6
7
8
9
@RestController
@RequestMapping("/consul")
public class ConsulController {

    @GetMapping(value = "/test", produces = MediaType.APPLICATION_PROBLEM_JSON_VALUE)
    public Result test() {
        return Result.ok("consul 访问成功");
    }
}
1
2
3
4
5
6
7
8
9
上次更新: 10/29/2024, 10:27:50 AM