当前位置: 首页 > news >正文

go-zero开发入门之网关往rpc服务传递数据2

go-zero 的网关服务实际是个 go-zero 的 API 服务,也就是一个 http 服务,或者说 rest 服务。http 转 grpc 使用了开源的 grpcurl 库,当网关需要往 rpc 服务传递额外的数据,比如鉴权数据的时候,通过 http 的 header 进行:

func AuthMiddleware(next http.HandlerFunc, w http.ResponseWriter, r *http.Request) {authResp, err := authClient.Authenticate(r.Context(), &authReq) // 调用鉴权服务r.Header.Set("Grpc-Metadata-myuid", authResp.UserId) // 往 rpc 服务传递额外数据next.ServeHTTP(w, r)
}

rpc 服务端从 metadata 取出数据:

func (l *QueryUserLogic) QueryUser(in *user.UserReq) (*user.UserResp, error) {vals := metadata.ValueFromIncomingContext(l.ctx, "gateway-myuid")uid = vals[0]
}

这里有两个需要注意的地方,在网关侧的名必须以“Grpc-Metadata-”打头,而 rpc 服务端必须以“gateway-”打头,这是 go-zero 的 gateway/internal/headerprocessor.go 写死的规则:

const (metadataHeaderPrefix = "Grpc-Metadata-"metadataPrefix       = "gateway-"
)// ProcessHeaders builds the headers for the gateway from HTTP headers.
func ProcessHeaders(header http.Header) []string {var headers []stringfor k, v := range header {if !strings.HasPrefix(k, metadataHeaderPrefix) { // 判断是否以“Grpc-Metadata-”打头(网关侧传递的)continue // 非以“Grpc-Metadata-”打头的都会被丢弃掉}key := fmt.Sprintf("%s%s", metadataPrefix, strings.TrimPrefix(k, metadataHeaderPrefix)) // 替换为新的前缀“gateway-”(rpc 服务端看到的)for _, vv := range v {headers = append(headers, key+":"+vv)}}return headers
}

调用栈:

(dlv) bt0  0x00000000019da092 in github.com/zeromicro/go-zero/gateway/internal.ProcessHeadersat ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/gateway/internal/headerprocessor.go:151  0x00000000019dc40a in github.com/zeromicro/go-zero/gateway.(*Server).prepareMetadataat ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/gateway/server.go:1752  0x00000000019dbf69 in github.com/zeromicro/go-zero/gateway.(*Server).buildHandler.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/gateway/server.go:1323  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:21224  0x00000000008ca162 in net/http.Handler.ServeHTTP-fmat <autogenerated>:15  0x000000000195adc5 in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:21226  0x000000000195adc5 in gateway/middleware.AuthMiddleware // 网关代码at ./Getting-Started-with-Go-zero/gateway_login/gateway/middleware/login_and_auth.go:987  0x000000000195a325 in gateway/middleware.LoginAndAuthMiddleware.func1at ./Getting-Started-with-Go-zero/gateway_login/gateway/middleware/login_and_auth.go:378  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:21229  0x0000000001969169 in github.com/zeromicro/go-zero/rest/handler.GunzipHandler.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/gunziphandler.go:26
10  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
11  0x000000000196b3bf in github.com/zeromicro/go-zero/rest/handler.MaxBytesHandler.func2.1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/maxbyteshandler.go:24
12  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
13  0x000000000196ba15 in github.com/zeromicro/go-zero/rest/handler.MetricHandler.func1.1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/metrichandler.go:21
14  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
15  0x000000000196c243 in github.com/zeromicro/go-zero/rest/handler.RecoverHandler.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/recoverhandler.go:21
16  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
17  0x000000000196d45c in github.com/zeromicro/go-zero/rest/handler.(*timeoutHandler).ServeHTTP.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/timeouthandler.go:82
18  0x0000000000471921 in runtime.goexitat /usr/local/go/src/runtime/asm_amd64.s:1598(dlv) bt0  0x00000000019d636a in google.golang.org/grpc/metadata.NewOutgoingContextat ./go/pkg/mod/google.golang.org/grpc@v1.59.0/metadata/metadata.go:1651  0x00000000019d636a in github.com/fullstorydev/grpcurl.InvokeRPCat ./go/pkg/mod/github.com/fullstorydev/grpcurl@v1.8.9/invoke.go:1362  0x00000000019dc058 in github.com/zeromicro/go-zero/gateway.(*Server).buildHandler.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/gateway/server.go:1323  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:21224  0x00000000008ca162 in net/http.Handler.ServeHTTP-fmat <autogenerated>:15  0x000000000195adc5 in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:21226  0x000000000195adc5 in gateway/middleware.AuthMiddleware // 网关代码at ./Getting-Started-with-Go-zero/gateway_login/gateway/middleware/login_and_auth.go:987  0x000000000195a325 in gateway/middleware.LoginAndAuthMiddleware.func1at ./Getting-Started-with-Go-zero/gateway_login/gateway/middleware/login_and_auth.go:378  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:21229  0x0000000001969169 in github.com/zeromicro/go-zero/rest/handler.GunzipHandler.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/gunziphandler.go:26
10  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
11  0x000000000196b3bf in github.com/zeromicro/go-zero/rest/handler.MaxBytesHandler.func2.1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/maxbyteshandler.go:24
12  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
13  0x000000000196ba15 in github.com/zeromicro/go-zero/rest/handler.MetricHandler.func1.1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/metrichandler.go:21
14  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
15  0x000000000196c243 in github.com/zeromicro/go-zero/rest/handler.RecoverHandler.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/recoverhandler.go:21
16  0x000000000089f52f in net/http.HandlerFunc.ServeHTTPat /usr/local/go/src/net/http/server.go:2122
17  0x000000000196d45c in github.com/zeromicro/go-zero/rest/handler.(*timeoutHandler).ServeHTTP.func1at ./go/pkg/mod/github.com/zeromicro/go-zero@v1.6.0/rest/handler/timeouthandler.go:82
18  0x0000000000471921 in runtime.goexitat /usr/local/go/src/runtime/asm_amd64.s:1598

在文件 zrpc/internal/clientinterceptors/tracinginterceptor.go 中调用了 metadata.NewOutgoingContext:

func startSpan(ctx context.Context, method, target string) (context.Context, trace.Span) {md, ok := metadata.FromOutgoingContext(ctx)if !ok {md = metadata.MD{}}tr := otel.Tracer(ztrace.TraceName)name, attr := ztrace.SpanInfo(method, target)ctx, span := tr.Start(ctx, name, trace.WithSpanKind(trace.SpanKindClient),trace.WithAttributes(attr...))ztrace.Inject(ctx, otel.GetTextMapPropagator(), &md)ctx = metadata.NewOutgoingContext(ctx, md)return ctx, span
}// UnaryTracingInterceptor returns a grpc.UnaryClientInterceptor for opentelemetry.
func UnaryTracingInterceptor(ctx context.Context, method string, req, reply any,cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {ctx, span := startSpan(ctx, method, cc.Target())defer span.End()ztrace.MessageSent.Event(ctx, 1, req)err := invoker(ctx, method, req, reply, cc, opts...)ztrace.MessageReceived.Event(ctx, 1, reply)if err != nil {s, ok := status.FromError(err)if ok {span.SetStatus(codes.Error, s.Message())span.SetAttributes(ztrace.StatusCodeAttr(s.Code()))} else {span.SetStatus(codes.Error, err.Error())}return err}span.SetAttributes(ztrace.StatusCodeAttr(gcodes.OK))return nil
}

拦截器:

./zrpc/internal/rpcserver.go:		interceptors = append(interceptors, serverinterceptors.UnaryTracingInterceptor)
./zrpc/internal/client.go:		interceptors = append(interceptors, clientinterceptors.UnaryTracingInterceptor)

服务端代码:

//zrpc/internal/rpcserver.go
func (s *rpcServer) buildUnaryInterceptors() []grpc.UnaryServerInterceptor {var interceptors []grpc.UnaryServerInterceptorif s.middlewares.Trace {interceptors = append(interceptors, serverinterceptors.UnaryTracingInterceptor)}if s.middlewares.Recover {interceptors = append(interceptors, serverinterceptors.UnaryRecoverInterceptor)}if s.middlewares.Stat {interceptors = append(interceptors,serverinterceptors.UnaryStatInterceptor(s.metrics, s.middlewares.StatConf))}if s.middlewares.Prometheus {interceptors = append(interceptors, serverinterceptors.UnaryPrometheusInterceptor)}if s.middlewares.Breaker {interceptors = append(interceptors, serverinterceptors.UnaryBreakerInterceptor)}return append(interceptors, s.unaryInterceptors...)
}func (s *rpcServer) Start(register RegisterFn) error {lis, err := net.Listen("tcp", s.address)if err != nil {return err}unaryInterceptorOption := grpc.ChainUnaryInterceptor(s.buildUnaryInterceptors()...)streamInterceptorOption := grpc.ChainStreamInterceptor(s.buildStreamInterceptors()...)options := append(s.options, unaryInterceptorOption, streamInterceptorOption)server := grpc.NewServer(options...)register(server)// register the health check serviceif s.health != nil {grpc_health_v1.RegisterHealthServer(server, s.health)s.health.Resume()}s.healthManager.MarkReady()health.AddProbe(s.healthManager)// we need to make sure all others are wrapped up,// so we do graceful stop at shutdown phase instead of wrap up phasewaitForCalled := proc.AddShutdownListener(func() {if s.health != nil {s.health.Shutdown()}server.GracefulStop()})defer waitForCalled()return server.Serve(lis)
}

客户端代码:

//zrpc/internal/client.go
func (c *client) buildUnaryInterceptors(timeout time.Duration) []grpc.UnaryClientInterceptor {var interceptors []grpc.UnaryClientInterceptorif c.middlewares.Trace {interceptors = append(interceptors, clientinterceptors.UnaryTracingInterceptor)}if c.middlewares.Duration {interceptors = append(interceptors, clientinterceptors.DurationInterceptor)}if c.middlewares.Prometheus {interceptors = append(interceptors, clientinterceptors.PrometheusInterceptor)}if c.middlewares.Breaker {interceptors = append(interceptors, clientinterceptors.BreakerInterceptor)}if c.middlewares.Timeout {interceptors = append(interceptors, clientinterceptors.TimeoutInterceptor(timeout))}return interceptors
}func (c *client) buildDialOptions(opts ...ClientOption) []grpc.DialOption {var cliOpts ClientOptionsfor _, opt := range opts {opt(&cliOpts)}var options []grpc.DialOptionif !cliOpts.Secure {options = append([]grpc.DialOption(nil),grpc.WithTransportCredentials(insecure.NewCredentials()))}if !cliOpts.NonBlock {options = append(options, grpc.WithBlock())}options = append(options,grpc.WithChainUnaryInterceptor(c.buildUnaryInterceptors(cliOpts.Timeout)...),grpc.WithChainStreamInterceptor(c.buildStreamInterceptors()...),)return append(options, cliOpts.DialOptions...)
}func (c *client) dial(server string, opts ...ClientOption) error {options := c.buildDialOptions(opts...)timeCtx, cancel := context.WithTimeout(context.Background(), dialTimeout)defer cancel()conn, err := grpc.DialContext(timeCtx, server, options...)if err != nil {service := serverif errors.Is(err, context.DeadlineExceeded) {pos := strings.LastIndexByte(server, separator)// len(server) - 1 is the index of last charif 0 < pos && pos < len(server)-1 {service = server[pos+1:]}}return fmt.Errorf("rpc dial: %s, error: %s, make sure rpc service %q is already started",server, err.Error(), service)}c.conn = connreturn nil
}// NewClient returns a Client.
func NewClient(target string, middlewares ClientMiddlewaresConf, opts ...ClientOption) (Client, error) {cli := client{middlewares: middlewares,}svcCfg := fmt.Sprintf(`{"loadBalancingPolicy":"%s"}`, p2c.Name)balancerOpt := WithDialOption(grpc.WithDefaultServiceConfig(svcCfg))opts = append([]ClientOption{balancerOpt}, opts...)if err := cli.dial(target, opts...); err != nil {return nil, err}return &cli, nil
}

相关文章:

go-zero开发入门之网关往rpc服务传递数据2

go-zero 的网关服务实际是个 go-zero 的 API 服务&#xff0c;也就是一个 http 服务&#xff0c;或者说 rest 服务。http 转 grpc 使用了开源的 grpcurl 库&#xff0c;当网关需要往 rpc 服务传递额外的数据&#xff0c;比如鉴权数据的时候&#xff0c;通过 http 的 header 进行…...

Cron介绍,以及常见的cron表达式

目录 一.cron介绍 1.什么是Cron&#xff1f; 2.Cron语法 时间字段的取值范围如下&#xff1a; 时间字段支持以下特殊字符&#xff1a; 下面是一些示例&#xff1a; 3.虚拟机安装cron(centos7展示) 二.常见的cron表达式 一.cron介绍 1.什么是Cron&#xff1f; Cron是一个…...

智能优化算法应用:基于协作搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于协作搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于协作搜索算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.协作搜索算法4.实验参数设定5.算法结果6.…...

分布式训练通信NCCL之Ring-Allreduce详解

&#x1f380;个人主页&#xff1a; https://zhangxiaoshu.blog.csdn.net &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️&#xff0c;如有错误敬请指正! &#x1f495;未来很长&#xff0c;值得我们全力奔赴更美好的生活&…...

os_util 工具类和方法的实现

一、前置说明 总体目录&#xff1a;《从 0-1 搭建企业级 APP 自动化测试框架》上节回顾&#xff1a;在 init_appium_and_devices 的实现思路分析 小节中&#xff0c;分析了实现 init_appium_and_devices 的思路&#xff0c;梳理出了必要的工具类和方法。本节目标&#xff1a;完…...

uview表单校验带星号

uView表单校验带星号可以通过设置required属性来实现。在uView中&#xff0c;可以使用组件来实现表单校验&#xff0c;具体步骤如下&#xff1a; 1、在需要校验的表单元素上添加required属性&#xff0c;例如&#xff1a; <u-form :model"detailInfo" ref"d…...

vue+element实现动态表格:根据后台返回的属性名和字段动态生成可变表格

现有一个胡萝卜厂生产不同品种的胡萝卜&#xff0c;为了便于客户了解产品&#xff0c;现需在官网展示胡萝卜信息。现有的萝卜信息&#xff1a;编号&#xff08;id&#xff09;、名称&#xff08;name&#xff09;、保质期&#xff08;age&#xff09;、特点&#xff08;remark&…...

云渲染UE4像素流送搭建(winows、ubuntu单实例与多实例像素流送)

windows/ubuntu20.4下UE4.27.2像素流送 像素流送技术可以将服务器端打包的虚幻引擎应用程序在客户端的浏览器上运行&#xff0c;用户可以通过浏览器操作虚幻引擎应用程序&#xff0c;客户端无需下载虚幻引擎&#xff0c;本文实现两台机器通过物理介质网线实现虚幻引擎应用程序…...

Unity VR Pico apk安装失败:INSTALL_FAILED_UPDATE_INCOMPATIBLE

我的报错&#xff1a; PICO4企业版。安装apk&#xff0c;报错“安装失败。&#xff08;所属的Unity项目打包的apk&#xff0c;被我在同一台pico4安装了20次&#xff09; 调试方法&#xff1a; PIco4发布使用UNITY开发的Vr应用&#xff0c;格式为apk&#xff0c;安装的时候发生…...

Prompt 提示工程学习笔记

一、Prompt设计的四个关键要素&#xff1a; 任务描述、输入数据、上下文信息、提示风格 &#xff08;1&#xff09;任务描述&#xff1a;描述想要让LLM遵循的指令。描述应详细清晰&#xff0c;可进一步使用关键词突出特殊设置&#xff0c;从而更好地指导LLM工作。 &#xff0…...

STM32实现三个小灯亮

led.c #include"led.h"void Led_Init(void) {GPIO_InitTypeDef GPIO_VALUE; //???RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//???GPIO_VALUE.GPIO_ModeGPIO_Mode_Out_PP;//???? ????GPIO_VALUE.GPIO_PinGPIO_Pin_1|GPIO_Pin_2|GPIO_P…...

1861_什么是H桥

Grey 全部学习内容汇总&#xff1a; GitHub - GreyZhang/g_hardware_basic: You should learn some hardware design knowledge in case hardware engineer would ask you to prove your software is right when their hardware design is wrong! 1861_什么是H桥 H桥电路可以…...

【计算机四级(网络工程师)笔记】操作系统运行机制

目录 一、中央处理器&#xff08;CPU&#xff09; 1.1CPU的状态 1.2指令分类 二、寄存器 2.1寄存器分类 2.2程序状态字&#xff08;PSW&#xff09; 三、系统调用 3.1系统调用与一般过程调用的区别 3.2系统调用的分类 四、中断与异常 4.1中断 4.2异常 &#x1f308;嗨&#xff…...

Swagger快速入门

1、Swagger快速入门 1.1 swagger介绍 官网&#xff1a;https://swagger.io/ Swagger 是一个规范和完整的Web API框架&#xff0c;用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 功能主要包含以下几点: A. 使得前后端分离开发更加方便&#xff0c;有利于团队协作…...

数据结构之<堆>的介绍

1.简介 堆是一种特殊的数据结构&#xff0c;通常用于实现优先队列。堆是一个可以被看作近似完全二叉树的结构&#xff0c;并且具有一些特殊的性质&#xff0c;根据这些性质&#xff0c;堆被分为最大堆&#xff08;或者大根堆&#xff0c;大顶堆&#xff09;和最小堆两种。 2.…...

使用Ubuntu22+Minikube快速搭建K8S开发环境

安装Vmware 这一步&#xff0c;可以参考我的如下课程。 安装Ubuntu22 下载ISO镜像 这里我推荐从清华镜像源下载&#xff0c;速度会快非常多。 下载地址&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/22.04.3/ 如果你报名了我的这门视频课程&#xf…...

【中小型企业网络实战案例 二】配置网络互连互通

​【中小型企业网络实战案例 一】规划、需求和基本配置-CSDN博客 热门IT技术视频教程&#xff1a;https://xmws-it.blog.csdn.net/article/details/134398330?spm1001.2014.3001.5502 配置接入层交换机 1.以接入交换机ACC1为例&#xff0c;创建ACC1的业务VLAN 10和20。 <…...

Azure Machine Learning - Azure OpenAI GPT 3.5 Turbo 微调教程

本教程将引导你在Azure平台完成对 gpt-35-turbo-0613 模型的微调。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认证的资深架构师&…...

运维大模型探索之 Text2PromQL 问答机器人

作者&#xff1a;陈昆仪&#xff08;图杨&#xff09; 大家下午好&#xff0c;我是来自阿里云可观测团队的算法工程师陈昆仪。今天分享的主题是“和我交谈并获得您想要的PromQL”。今天我跟大家分享在将AIGC技术运用到可观测领域的探索。 今天分享主要包括5个部分&#xff1a;…...

虚拟机VMware:变动ip修改固定ip

1、配置ip地址 vi /etc/sysconfig/network-scripts/ifcfg-ens33修改为&#xff1a; 修改如下&#xff1a;TYPE"Ethernet" # 网络类型为以太网 BOOTPROTO"static" # 手动分配ip NAME"ens33" # 网卡…...

5分钟快速上手:AnythingtoRealCharacters2511动漫图片转真人照片教程

5分钟快速上手&#xff1a;AnythingtoRealCharacters2511动漫图片转真人照片教程 1. 认识你的动漫转真人工具 1.1 工具能做什么&#xff1f; AnythingtoRealCharacters2511是一个专门将动漫图片转化为真人照片的AI工具。它基于Qwen-Image-Edit模型开发&#xff0c;特别擅长处…...

从安全卫士到AI指挥官:周鸿祎的“AI突围”实录!

2026年3月27日&#xff0c;北京——在360总部楼下&#xff0c;一张临时搭建的长桌上&#xff0c;周鸿祎身穿印有“AI世界”的黑色工装马甲&#xff0c;手握键盘&#xff0c;亲自为现场观众“装龙虾”。这幅画面不仅让人恍惚回到十几年前的中关村&#xff0c;也标志着一场关于AI…...

Hive3.1.3安装避坑指南:从下载到配置的完整流程(含MySQL元数据迁移)

Hive3.1.3企业级部署实战&#xff1a;MySQL元数据管理与性能调优全解析 在大数据生态系统中&#xff0c;Hive始终扮演着数据仓库核心组件的角色。尽管实时计算框架日益流行&#xff0c;但据统计&#xff0c;超过78%的企业级数据仓库仍在使用Hive处理TB级以上的历史数据分析任务…...

终极指南:如何让Nautilus、Dolphin等Linux文件管理器拥有macOS Finder般流畅的快捷键体验

终极指南&#xff1a;如何让Nautilus、Dolphin等Linux文件管理器拥有macOS Finder般流畅的快捷键体验 【免费下载链接】kinto Mac-style shortcut keys for Linux & Windows. 项目地址: https://gitcode.com/gh_mirrors/kin/kinto 你是否厌倦了在Linux文件管理器中不…...

如何通过Superalgos教育模块快速掌握算法交易:新手入门完整指南

如何通过Superalgos教育模块快速掌握算法交易&#xff1a;新手入门完整指南 【免费下载链接】Superalgos Superalgos/Superalgos: 是一个开源的分布式社交网络分析和数据挖掘平台。适合对大数据分析、机器学习、区块链以及分布式系统有兴趣的开发者。 项目地址: https://gitc…...

5年java开发经验总结面试题-内含完整答案

1、讲讲IO里面的常见类&#xff0c;字节流、字符流、接口、实现类、方法阻塞。 文件字节输入输出流 FileInputStream/FileOutputStream&#xff0c; 文件字符流 FileReader/FileWriter 包装流PrintStream/PrintWriter/Scanner 字符串输入输出流StringReader/StringWriter 转换流…...

石墨烯这玩意儿在COMSOL里折腾起来挺有意思的,特别是搞太赫兹和近红外的同学估计都遇到过选模型的纠结。今天咱们就聊点实战经验,顺便甩点代码片段

Comsol石墨烯二维材料。 包含太赫兹德鲁得和近红外Kubo两种模型。 共7个案例&#xff0c;包含参考文献。先说说太赫兹波段常用的德鲁得模型&#xff0c;这货相当于把石墨烯当经典等离子体处理。在COMSOL里实现时&#xff0c;关键要设置表面电流密度&#xff1a; sigma_drude (…...

东北老牌央国企陪跑机构哪家实力强

在东北地区&#xff0c;众多求职者&#xff0c;特别是应届毕业生&#xff0c;将目光投向了工作稳定、发展前景广阔的央国企。在这一背景下&#xff0c;专业的求职服务机构应运而生&#xff0c;为求职者提供系统化的支持。辽宁优泰教育咨询有限公司便是其中一家专注于该领域的服…...

告别蜗牛速度!优麒麟20.04 LTS换源华为云镜像保姆级教程

优麒麟20.04 LTS提速指南&#xff1a;华为云镜像配置全解析 每次在优麒麟上安装软件时&#xff0c;看着进度条像蜗牛一样缓慢前进&#xff0c;是不是让你感到无比焦虑&#xff1f;特别是当你急需某个工具完成工作时&#xff0c;漫长的等待简直让人抓狂。作为一款基于Ubuntu的国…...

从‘丐版’到‘神板’:深度拆解Raspberry Pi Zero 2 W的散热设计与性能压榨指南

从‘丐版’到‘神板’&#xff1a;深度拆解Raspberry Pi Zero 2 W的散热设计与性能压榨指南 当一款信用卡大小的开发板搭载四核处理器时&#xff0c;散热与性能的平衡便成为硬件极客们最热衷的挑战。Raspberry Pi Zero 2 W以不到15美元的定价&#xff0c;却藏着令人惊喜的工程智…...