死信队列监听补充

举报
赵KK日常技术记录 发表于 2023/06/29 23:21:16 2023/06/29
【摘要】 最近在做Spring cloud项目,在以前的demo中体验过Feign,整个cloud组件太多,暂时没时间整理,java并发编程系列估计还要1-2章吧,demo不是很好找,结合最近的见闻整理一下最近的问题。最近高频词:SpringCloud,Arthas,Spring Alibaba Nacos,Thymleaf复选框回显问题Springcloud我看下加一下我的笔记连接,Arthas我自...

最近在做Spring cloud项目,在以前的demo中体验过Feign,整个cloud组件太多,暂时没时间整理,java并发编程系列估计还要1-2章吧,demo不是很好找,结合最近的见闻整理一下最近的问题。

最近高频词:SpringCloud,Arthas,Spring Alibaba Nacos,Thymleaf复选框回显问题

Springcloud我看下加一下我的笔记连接,Arthas我自己写过一篇,但是太皮毛了,针对实际项目的排错和好多命令并没有试过,下面一一推荐下公众号,另外就是Spring Alibaba Nacos,这个也推一下小马哥的链接,另外描述下Thymleaf的复选框回显问题。

Spring cloud

随着微服务的流行,cloud现在用的越来越多,很多组件由于种种原因出现了停更,现在不描述太多的问题,说一下最近遇到的错,和Ribbon的负载均衡算法。

1.Feign:服务端面向接口式的客户端负载均衡组件
用法在笔记里有,先看下常见报错

org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘requestMappingHandlerMapping’ defined in class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Invocation of init method failed; nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map ‘xxx’ method
public xxx
to {[xxx]}: There is already ‘xxx’ bean method
关键词

Ambiguous mapping. Cannot map ‘xxx’ method

这类报错一定是在声明Feign接口时,请求的RequestMapping地址存在重复

例如两个Feign接口,应用了同一个@GetMapping(value = “payment/get/{id}”)地址

@Component
@FeignClient(value = “CLOUD-PAYMENT-SERVICE”)
public interface FeignClientService {
/**
* 根据id查询
*
* @param id
* @return
*/
@GetMapping(value = “payment/get/{id}”)
CommonResult getPaymentById(@PathVariable(“id”) Long id);

/**
 * 模拟feign超时
 *
 * @return
 */
@GetMapping(value = "/payment/feign/timeout")
String paymentFeignTimeout();

}
2.Ribbon负载均衡算法

Ribbon负载均衡客户端 Consumer Load Balancer

官网:https://github.com/Netflix/ribbon/wiki/Getting-Started

未来替换SpringCloud loadBalancer

Nginx是服务器负载均衡 集中式 客户端请求交由Nginx处理

Ribbon本地负载均衡 进程内

负载均衡算法:轮询,随机,权重等

eureka包含了Ribbon

点击eureka pom依赖

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> ↓ <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-archaius</artifactId> <version>2.2.1.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-ribbon</artifactId> <version>2.2.1.RELEASE</version> <scope>compile</scope> </dependency>

图片

看一下Ribbon的核心组件IRule源码

/**

  • Interface that defines a “Rule” for a LoadBalancer. A Rule can be thought of
  • as a Strategy for loadbalacing. Well known loadbalancing strategies include
  • Round Robin, Response Time based etc.
  • 为LoadBalancer定义“规则”的接口。可以想出一个规则
    *作为负载平衡策略。众所周知的负载平衡策略包括
    *轮询、响应时间等
  • @author stonse

/
public interface IRule{
/

* choose one alive server from lb.allServers or
* lb.upServers according to key
*
* @return choosen Server object. NULL is returned if none
* server is available
*/

public Server choose(Object key);

public void setLoadBalancer(ILoadBalancer lb);

public ILoadBalancer getLoadBalancer();    

}
看下其实现

图片

源码

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**

  • The most well known and basic load balancing strategy, i.e. Round Robin Rule.
  • @author stonse
  • @author Nikos Michalakis nikos@netflix.com

*/
public class RoundRobinRule extends AbstractLoadBalancerRule {

private AtomicInteger nextServerCyclicCounter;//核心类
private static final boolean AVAILABLE_ONLY_SERVERS = true;
private static final boolean ALL_SERVERS = false;

private static Logger log = LoggerFactory.getLogger(RoundRobinRule.class);

public RoundRobinRule() {
    nextServerCyclicCounter = new AtomicInteger(0);
}

public RoundRobinRule(ILoadBalancer lb) {
    this();
    setLoadBalancer(lb);
}

public Server choose(ILoadBalancer lb, Object key) {
    if (lb == null) {
        log.warn("no load balancer");
        return null;
    }

    Server server = null;
    int count = 0;
    while (server == null && count++ < 10) {
        //选择活着的机器
        List<Server> reachableServers = lb.getReachableServers();
        List<Server> allServers = lb.getAllServers();
        int upCount = reachableServers.size();
        int serverCount = allServers.size();
        if ((upCount == 0) || (serverCount == 0)) {
            log.warn("No up servers available from load balancer: " + lb);
            return null;
        }
        servercount=集群总数
        int nextServerIndex = incrementAndGetModulo(serverCount);
        //获取服务下标  get(1)
        server = allServers.get(nextServerIndex);

        if (server == null) {
            /* Transient. */
            Thread.yield();
            continue;
        }

        if (server.isAlive() && (server.isReadyToServe())) {
            return (server);
        }

        // Next.
        server = null;
    }

    if (count >= 10) {
        log.warn("No available alive servers after 10 tries from load balancer: "
                + lb);
    }
    return server;
}

/**
 * Inspired by the implementation of {@link AtomicInteger#incrementAndGet()}.
 *
 * @param modulo The modulo to bound the value of the counter.
 * @return The next value.
 */
private int incrementAndGetModulo(int modulo) {
    for (;;) {
        int current = nextServerCyclicCounter.get();
        int next = (current + 1) % modulo;
        //CAS  
        if (nextServerCyclicCounter.compareAndSet(current, next))
            return next;
    }
}

@Override
public Server choose(Object key) {
    return choose(getLoadBalancer(), key);
}

@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}

}
原理是第几次请求%服务集群数量=实际服务下标,返回其服务

源码利用AtomicInteger +CAS算法实现

手写随机算法

定义获取服务器方法接口

public interface LoadBalancer {
/**
* 获取存活的服务实例列表
*
* @param serviceInstances
* @return
*/
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
利用AtomicInteger+cas实现

@Component
public class MyLB implements LoadBalancer {
private AtomicInteger atomicInteger = new AtomicInteger(0);

public final int getAndIncrement() {
    int current;
    int next;
    do {
        current = this.atomicInteger.get();
        // 超过最大值,为0,重新计数
        next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        // 自旋锁
    } while (!atomicInteger.compareAndSet(current, next));
    System.out.println("****第几次访问,次数next:" + next);
    return next;
}

/**
 * 负载均衡算法:rest接口第几次请求数%服务器集群总数量=实际调用服务器位置下标,每次服务重启动后rest接口计数从1开始.
 *
 * @param serviceInstances
 * @return
 */
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
    int index = getAndIncrement() % serviceInstances.size();
    return serviceInstances.get(index);
}

}
Controller调用

/**
* 路由规则: 轮询
* http://localhost/consumer/payment/payment/lb
*
* @return
*/
@GetMapping(value = “/consumer/payment/lb”)
public String getPaymentLB() {
List<ServiceInstance> instances = discoveryClient.getInstances(“CLOUD-PAYMENT-SERVICE”);
if (instances == null || instances.size() <= 0) {
return null;
}
ServiceInstance serviceInstance = loadBalancer.instances(instances);
URI uri = serviceInstance.getUri();
return restTemplate.getForObject(uri + “/payment/lb”, String.class);
}
Arthas

Arthas针对线上排错,定位线上BUG有很多命令操作,自己写的那篇入门太过简单,推荐文章

阿里问题定位神器 Arthas 的骚操作,定位线上BUG,超给力!

Spring Alibaba Nacos

Springcloud config 服务配置的替换

推荐视频https://www.bilibili.com/video/av32191103?p=1

Thymleaf复选框回显问题

这个问题我在以前文章提到过,只不过没现在了解的那么透彻我转载了CSDN一篇5万+访问量的文章,现在结合代码说明下

首先后台放入想要复选的值集合

public class MethodService {

public boolean contains(String id,List<Proof> proofs,ModelMap map){

    List<String> ids = new ArrayList<>();
    for(Proof p: proofs){
       ids.add(p.getId());
    }
    map.put("list",ids);
    return (ids.contains(id));
}

}

前台取值首先取到list,在判断是否包含当前value值如果包含返回true,页面回显选中

<label class="checkbox-inline i-checks" th:each="data : ${list}"> <input th:attr="checked=${methodService.contains(data.id,proofsList)?true:false}" type="checkbox" name="proofs[]" th:value="${data.id}" id="inlineCheckbox1" /> </lable> 附带Spring Cloud笔记链接

https://note.youdao.com/ynoteshare1/index.html?id=b5cd0830c14f59287ee8a053174c60df&type=note

我不想在未来的日子里

独自哭着无法往前

      歌曲《我还年轻 我还年轻》
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。